spontaneous 0.2.0.beta9 → 0.2.0.beta10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +61 -0
- data/LICENSE +18 -17
- data/Rakefile +1 -1
- data/application/css/core.css.scss +1 -1
- data/application/css/dialogue.css.scss +8 -20
- data/application/js/preview.js +28 -7
- data/application/js/publish.js +15 -4
- data/application/js/top_bar.js +0 -16
- data/application/js/views/piece_view.js +1 -1
- data/lib/spontaneous/asset/environment.rb +16 -1
- data/lib/spontaneous/box.rb +68 -0
- data/lib/spontaneous/capistrano/deploy.rb +7 -4
- data/lib/spontaneous/capistrano/sync.rb +2 -2
- data/lib/spontaneous/cli/init.rb +70 -19
- data/lib/spontaneous/cli/init/db.rb +34 -55
- data/lib/spontaneous/cli/init/mysql.rb +5 -5
- data/lib/spontaneous/cli/init/postgresql.rb +8 -9
- data/lib/spontaneous/cli/init/sqlite.rb +1 -2
- data/lib/spontaneous/cli/migrate.rb +0 -1
- data/lib/spontaneous/cli/site.rb +4 -0
- data/lib/spontaneous/collections/entry_set.rb +11 -0
- data/lib/spontaneous/data_mapper/content_model.rb +2 -0
- data/lib/spontaneous/data_mapper/content_model/serialization.rb +2 -2
- data/lib/spontaneous/extensions/array.rb +12 -2
- data/lib/spontaneous/field/base.rb +10 -0
- data/lib/spontaneous/field/file.rb +32 -2
- data/lib/spontaneous/field/image.rb +24 -2
- data/lib/spontaneous/field/select.rb +8 -0
- data/lib/spontaneous/field/webvideo.rb +8 -0
- data/lib/spontaneous/generators/site/config/initializers/fields.rb +55 -0
- data/lib/spontaneous/json.rb +3 -2
- data/lib/spontaneous/logger.rb +2 -2
- data/lib/spontaneous/media/file.rb +3 -3
- data/lib/spontaneous/media/image/attributes.rb +72 -6
- data/lib/spontaneous/media/image/renderable.rb +53 -20
- data/lib/spontaneous/media/store.rb +3 -3
- data/lib/spontaneous/media/store/backend.rb +16 -0
- data/lib/spontaneous/media/store/cloud.rb +52 -12
- data/lib/spontaneous/media/store/local.rb +6 -3
- data/lib/spontaneous/model.rb +3 -0
- data/lib/spontaneous/model/core/entries.rb +34 -13
- data/lib/spontaneous/model/core/entry.rb +3 -1
- data/lib/spontaneous/model/page/controllers.rb +1 -2
- data/lib/spontaneous/model/page/paths.rb +18 -7
- data/lib/spontaneous/output/context.rb +0 -8
- data/lib/spontaneous/output/template/renderer.rb +2 -0
- data/lib/spontaneous/plugins/application/state.rb +0 -4
- data/lib/spontaneous/prototypes/field_prototype.rb +4 -0
- data/lib/spontaneous/publishing/immediate.rb +0 -5
- data/lib/spontaneous/publishing/progress.rb +2 -2
- data/lib/spontaneous/publishing/rerender.rb +1 -4
- data/lib/spontaneous/publishing/simultaneous.rb +19 -17
- data/lib/spontaneous/publishing/steps.rb +12 -3
- data/lib/spontaneous/rack.rb +2 -0
- data/lib/spontaneous/rack/asset_server.rb +5 -2
- data/lib/spontaneous/rack/back.rb +9 -1
- data/lib/spontaneous/rack/back/base.rb +1 -0
- data/lib/spontaneous/rack/back/changes.rb +5 -0
- data/lib/spontaneous/rack/back/preview.rb +4 -4
- data/lib/spontaneous/rack/back/private.rb +11 -0
- data/lib/spontaneous/rack/middleware/scope.rb +16 -4
- data/lib/spontaneous/rack/page_controller.rb +2 -2
- data/lib/spontaneous/rack/public.rb +52 -4
- data/lib/spontaneous/sequel.rb +10 -13
- data/lib/spontaneous/site.rb +28 -8
- data/lib/spontaneous/site/publishing.rb +1 -1
- data/lib/spontaneous/site/storage.rb +7 -4
- data/lib/spontaneous/tasks/environment.rake +3 -0
- data/lib/spontaneous/utils/database/postgres_dumper.rb +23 -2
- data/lib/spontaneous/version.rb +1 -1
- data/spontaneous.gemspec +7 -12
- data/test/fixtures/assets/public1/css/data.css.scss +1 -1
- data/test/functional/test_application.rb +15 -0
- data/test/functional/test_cli.rb +109 -3
- data/test/functional/test_front.rb +108 -10
- data/test/test_helper.rb +3 -3
- data/test/unit/fields/test_boolean_fields.rb +80 -0
- data/test/unit/fields/test_date_fields.rb +47 -0
- data/test/unit/fields/test_file_field.rb +210 -0
- data/test/unit/{test_images.rb → fields/test_image_fields.rb} +133 -15
- data/test/unit/fields/test_location_fields.rb +41 -0
- data/test/unit/fields/test_option_fields.rb +61 -0
- data/test/unit/fields/test_tag_list_fields.rb +45 -0
- data/test/unit/fields/test_text_fields.rb +124 -0
- data/test/unit/fields/test_web_video_fields.rb +198 -0
- data/test/unit/test_assets.rb +22 -22
- data/test/unit/test_boxes.rb +34 -13
- data/test/unit/test_changesets.rb +1 -0
- data/test/unit/test_extensions.rb +17 -0
- data/test/unit/test_fields.rb +20 -643
- data/test/unit/test_media.rb +9 -9
- data/test/unit/test_page.rb +47 -0
- data/test/unit/test_publishing_pipeline.rb +2 -2
- data/test/unit/test_serialisation.rb +37 -0
- data/test/unit/test_storage.rb +42 -3
- metadata +37 -17
@@ -22,9 +22,11 @@ module Spontaneous::Publishing
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
def self.rerender
|
26
|
-
new do
|
27
|
-
|
25
|
+
def self.rerender(publishing_steps)
|
26
|
+
new([], publishing_steps.progress) do
|
27
|
+
RERENDER_STEPS.each do |step|
|
28
|
+
run step
|
29
|
+
end
|
28
30
|
end
|
29
31
|
end
|
30
32
|
|
@@ -140,6 +142,13 @@ module Spontaneous::Publishing
|
|
140
142
|
:archive_old_revisions
|
141
143
|
].freeze
|
142
144
|
|
145
|
+
RERENDER_STEPS = [
|
146
|
+
:render_revision,
|
147
|
+
:copy_assets,
|
148
|
+
:copy_static_files,
|
149
|
+
:generate_rackup_file
|
150
|
+
].freeze
|
151
|
+
|
143
152
|
CORE_PROGRESS = [:browser, :stdout].freeze
|
144
153
|
end
|
145
154
|
end
|
data/lib/spontaneous/rack.rb
CHANGED
@@ -15,6 +15,8 @@ module Spontaneous
|
|
15
15
|
HTTP_LAST_MODIFIED = "Last-Modified".freeze
|
16
16
|
HTTP_NO_CACHE = "max-age=0, must-revalidate, no-cache, no-store".freeze
|
17
17
|
|
18
|
+
SLASH = Spontaneous::Constants::SLASH
|
19
|
+
|
18
20
|
NAMESPACE = "/@spontaneous".freeze
|
19
21
|
AUTH_COOKIE = "spontaneous_api_key".freeze
|
20
22
|
SESSION_LIFETIME = 1.year
|
@@ -3,6 +3,8 @@ module Spontaneous::Rack
|
|
3
3
|
# header. This wrapper class proxies all requests to a Sprockets enviroment
|
4
4
|
# and adds in a charset setting to the content-type header of all responses
|
5
5
|
class AssetServer
|
6
|
+
CONTENT_TYPE = "Content-Type".freeze
|
7
|
+
|
6
8
|
def initialize(environment, charset = "UTF-8")
|
7
9
|
@environment, @charset = environment, charset
|
8
10
|
end
|
@@ -12,8 +14,9 @@ module Spontaneous::Rack
|
|
12
14
|
end
|
13
15
|
|
14
16
|
def force_encoding(status, headers, body)
|
15
|
-
content_type = headers[
|
16
|
-
|
17
|
+
if (content_type = headers[CONTENT_TYPE])
|
18
|
+
headers.update(CONTENT_TYPE => "#{content_type}; charset=#{@charset}")
|
19
|
+
end
|
17
20
|
[status, headers, body]
|
18
21
|
end
|
19
22
|
end
|
@@ -18,6 +18,7 @@ module Spontaneous
|
|
18
18
|
autoload :Map, 'spontaneous/rack/back/map'
|
19
19
|
autoload :Page, 'spontaneous/rack/back/page'
|
20
20
|
autoload :Preview, 'spontaneous/rack/back/preview'
|
21
|
+
autoload :Private, 'spontaneous/rack/back/private'
|
21
22
|
autoload :Schema, 'spontaneous/rack/back/schema'
|
22
23
|
autoload :Site, 'spontaneous/rack/back/site'
|
23
24
|
autoload :SiteAssets, 'spontaneous/rack/back/site_assets'
|
@@ -48,6 +49,7 @@ module Spontaneous
|
|
48
49
|
|
49
50
|
def self.editing_app(site)
|
50
51
|
::Rack::Builder.app do
|
52
|
+
use ::Rack::ShowExceptions if site.development?
|
51
53
|
use Scope::Edit, site
|
52
54
|
use Transaction, site
|
53
55
|
use ApplicationAssets
|
@@ -62,6 +64,10 @@ module Spontaneous
|
|
62
64
|
map("/schema") { run Schema }
|
63
65
|
use Reloader, site
|
64
66
|
use Index
|
67
|
+
map("/private") {
|
68
|
+
use Scope::Preview, site
|
69
|
+
run Private
|
70
|
+
}
|
65
71
|
use CSRF::Verification # Everything after this middleware requires a valid CSRF token
|
66
72
|
Back.api_handlers.each do |path, app|
|
67
73
|
map(path) { run app }
|
@@ -73,6 +79,7 @@ module Spontaneous
|
|
73
79
|
|
74
80
|
def self.preview_app(site)
|
75
81
|
::Rack::Builder.app do
|
82
|
+
use ::Rack::ShowExceptions if site.development?
|
76
83
|
use ::Rack::Lint if Spontaneous.development?
|
77
84
|
use Scope::Preview, site
|
78
85
|
use Transaction, site
|
@@ -84,7 +91,6 @@ module Spontaneous
|
|
84
91
|
# the preview site.
|
85
92
|
use Authenticate::Preview
|
86
93
|
use CSRF::Header
|
87
|
-
map("/assets") { run SiteAssets.new }
|
88
94
|
use Spontaneous::Rack::Static, root: Spontaneous.root / "public", urls: %w[/], try: ['.html', 'index.html', '/index.html']
|
89
95
|
use Reloader, site
|
90
96
|
# inject the front controllers into the preview so that this is a
|
@@ -128,6 +134,8 @@ module Spontaneous
|
|
128
134
|
end
|
129
135
|
end if site
|
130
136
|
|
137
|
+
map("/assets") { run SiteAssets.new }
|
138
|
+
|
131
139
|
map "/media" do
|
132
140
|
use ::Rack::Lint
|
133
141
|
run Spontaneous::Rack::CacheableFile.new(Spontaneous.media_dir)
|
@@ -2,12 +2,12 @@ module Spontaneous::Rack::Back
|
|
2
2
|
class Preview < Base
|
3
3
|
include Spontaneous::Rack::Public
|
4
4
|
|
5
|
+
set :show_exceptions, proc { Spontaneous.development? || Spontaneous.test? }
|
6
|
+
|
5
7
|
# In preview mode we want to find pages even if they're
|
6
8
|
# invisible.
|
7
|
-
def
|
8
|
-
site.model.scope
|
9
|
-
site.by_path(path)
|
10
|
-
end
|
9
|
+
def with_scope(&block)
|
10
|
+
site.model.scope(&block)
|
11
11
|
end
|
12
12
|
|
13
13
|
# Redirect to the edit UI if a preview page is being accessed directly
|
@@ -41,7 +41,7 @@ module Spontaneous::Rack::Middleware
|
|
41
41
|
end
|
42
42
|
|
43
43
|
POWERED_BY = {
|
44
|
-
"X-Powered-By" => "Spontaneous
|
44
|
+
"X-Powered-By" => "Spontaneous v#{Spontaneous::VERSION} <http://spontaneous.io>"
|
45
45
|
}
|
46
46
|
|
47
47
|
class Front < Base
|
@@ -49,18 +49,30 @@ module Spontaneous::Rack::Middleware
|
|
49
49
|
|
50
50
|
def initialize(app, site, options = {})
|
51
51
|
super
|
52
|
-
@renderer = Spontaneous::Output.published_renderer(@site)
|
53
52
|
end
|
54
53
|
|
55
54
|
def call!(env)
|
56
55
|
status = headers = body = nil
|
57
|
-
env[RENDERER] =
|
58
|
-
env[REVISION] = @site.published_revision
|
56
|
+
env[RENDERER] = renderer
|
57
|
+
env[REVISION] = revision = @site.published_revision
|
59
58
|
@site.model.with_published(@site) do
|
60
59
|
status, headers, body = @app.call(env)
|
61
60
|
end
|
62
61
|
[status, headers.merge(POWERED_BY), body]
|
63
62
|
end
|
63
|
+
|
64
|
+
def renderer
|
65
|
+
return renderer_for_revision if development?
|
66
|
+
@renderer ||= renderer_for_revision
|
67
|
+
end
|
68
|
+
|
69
|
+
def renderer_for_revision
|
70
|
+
Spontaneous::Output.published_renderer(@site)
|
71
|
+
end
|
72
|
+
|
73
|
+
def development?
|
74
|
+
Spontaneous.development?
|
75
|
+
end
|
64
76
|
end
|
65
77
|
end
|
66
78
|
end
|
@@ -6,7 +6,7 @@ module Spontaneous::Rack
|
|
6
6
|
class PageController < Sinatra::Base
|
7
7
|
class << self
|
8
8
|
# We wrap Sinatra's route methods in order to do two things:
|
9
|
-
# 1. To provide a path of '
|
9
|
+
# 1. To provide a path of '*' when none is given and
|
10
10
|
# 2. To register the presence of a handler for each method in order to
|
11
11
|
# correctly respond to the #dynamic? test
|
12
12
|
def get(*args, &bk) __dynamic!(:get, super(*__route_args(args), &bk)) end
|
@@ -28,7 +28,7 @@ module Spontaneous::Rack
|
|
28
28
|
|
29
29
|
def __route_args(args)
|
30
30
|
opts = args.extract_options!
|
31
|
-
path = String === args.first ? args.first :
|
31
|
+
path = (String === args.first) ? args.first : S::Constants::SLASH
|
32
32
|
[path, opts]
|
33
33
|
end
|
34
34
|
|
@@ -87,12 +87,52 @@ module Spontaneous
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def find_page!(path)
|
90
|
+
@controller_path = SLASH
|
90
91
|
@path, @output, @action = parse_path(path)
|
91
92
|
@page = find_page_by_path(@path)
|
92
93
|
end
|
93
94
|
|
94
95
|
def find_page_by_path(path)
|
95
|
-
site.by_path(path)
|
96
|
+
with_scope { site.by_path(path) || find_page_with_wildcards(path) }
|
97
|
+
end
|
98
|
+
|
99
|
+
# if we get to here it's because the path hasn't been found. This will get called for
|
100
|
+
# every request where the request doesn’t resolve to a path found in the db
|
101
|
+
# and will always try the site homepage as a last resort. So if you need many dynamic
|
102
|
+
# routes to resolve to a single page, e.g. for a single page app, then you just
|
103
|
+
# need to accept all those routes in a controller on the class of the site’s homepage
|
104
|
+
# and render your SPA template from that, e.g.
|
105
|
+
#
|
106
|
+
# class Homepage < Page
|
107
|
+
# controller do
|
108
|
+
# get '/app*' do
|
109
|
+
# render
|
110
|
+
# end
|
111
|
+
# end
|
112
|
+
# end
|
113
|
+
#
|
114
|
+
def find_page_with_wildcards(path)
|
115
|
+
parts = path.split('/')
|
116
|
+
length = parts.length - 2
|
117
|
+
range = (1..length).to_a.reverse
|
118
|
+
|
119
|
+
# make sure we go all the way back to the site homepage
|
120
|
+
try = range.map { |l| parts[0..l].join(SLASH) }.push(SLASH)
|
121
|
+
candidate = site.model::Page.where(path: try).order(Sequel.desc(:depth)).first
|
122
|
+
return nil if candidate.nil? || !candidate.dynamic?(request.request_method)
|
123
|
+
|
124
|
+
# don't pass the full path of the request to the controller, just
|
125
|
+
# the bit after the candidate page’s path.
|
126
|
+
cpath = candidate.path
|
127
|
+
@controller_path = path.slice(cpath.length, path.length - cpath.length)
|
128
|
+
|
129
|
+
# special handling of root, as always so that a controller on the root page that
|
130
|
+
# matches '/', e.g. `get '/'` is passed a path that starts with '/'
|
131
|
+
if cpath == SLASH
|
132
|
+
@controller_path.insert(0, SLASH)
|
133
|
+
end
|
134
|
+
|
135
|
+
candidate
|
96
136
|
end
|
97
137
|
|
98
138
|
def output(name)
|
@@ -106,7 +146,7 @@ module Spontaneous
|
|
106
146
|
def render_get
|
107
147
|
return call_action! if @action
|
108
148
|
if page.dynamic?(request.request_method)
|
109
|
-
invoke_action { page.process_root_action(site,
|
149
|
+
invoke_action { page.process_root_action(site, env_for_action, @output) }
|
110
150
|
else
|
111
151
|
render_page_with_output
|
112
152
|
end
|
@@ -119,11 +159,15 @@ module Spontaneous
|
|
119
159
|
|
120
160
|
return call_action! if @action
|
121
161
|
|
122
|
-
invoke_action { page.process_root_action(site,
|
162
|
+
invoke_action { page.process_root_action(site, env_for_action, @output) }
|
123
163
|
end
|
124
164
|
|
125
165
|
def call_action!
|
126
|
-
invoke_action { @page.process_action(site, action,
|
166
|
+
invoke_action { @page.process_action(site, action, env_for_action, @output) }
|
167
|
+
end
|
168
|
+
|
169
|
+
def env_for_action
|
170
|
+
env.merge(S::Constants::PATH_INFO => @controller_path)
|
127
171
|
end
|
128
172
|
|
129
173
|
def invoke_action
|
@@ -185,6 +229,10 @@ module Spontaneous
|
|
185
229
|
def not_found!
|
186
230
|
404
|
187
231
|
end
|
232
|
+
|
233
|
+
def with_scope
|
234
|
+
yield
|
235
|
+
end
|
188
236
|
end
|
189
237
|
end
|
190
238
|
end
|
data/lib/spontaneous/sequel.rb
CHANGED
@@ -2,16 +2,13 @@ require "sequel"
|
|
2
2
|
|
3
3
|
Sequel.extension :inflector
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
#
|
13
|
-
#
|
14
|
-
|
15
|
-
# lambda { |v| Oj.load(v, symbol_keys: true) }
|
16
|
-
# )
|
17
|
-
|
5
|
+
# See http://sequel.jeremyevans.net/rdoc/classes/Sequel/Timezones.html
|
6
|
+
# UTC is more performant than :local (or 'nil' which just fallsback to :local)
|
7
|
+
# A basic profiling run gives a 2 x performance improvement of :utc over :local
|
8
|
+
# With ~240 rows, timing ::Content.all gives:
|
9
|
+
#
|
10
|
+
# :utc ~0.04s
|
11
|
+
# :local ~0.08s
|
12
|
+
#
|
13
|
+
# DB timestamps are only shown in the editing UI & could be localized there per-user
|
14
|
+
Sequel.default_timezone = :utc
|
data/lib/spontaneous/site.rb
CHANGED
@@ -84,19 +84,31 @@ module Spontaneous
|
|
84
84
|
|
85
85
|
|
86
86
|
def connect_to_database!
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
87
|
+
self.database = database_instance(db_settings).tap do |db|
|
88
|
+
db.logger = logger if config.log_queries
|
89
|
+
# Improve performance for postgres
|
90
|
+
db.optimize_model_load = true if db.respond_to?(:optimize_model_load)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def database_instance(opts)
|
95
|
+
Sequel.connect(opts)
|
92
96
|
end
|
93
97
|
|
94
98
|
def db_settings
|
95
|
-
self.config.db
|
99
|
+
self.config.db ||= db_connection_options(environment)
|
96
100
|
end
|
97
101
|
|
98
|
-
def
|
99
|
-
|
102
|
+
def db_connection_options(env)
|
103
|
+
(db_config_env || db_config_file[env])
|
104
|
+
end
|
105
|
+
|
106
|
+
def db_config_env
|
107
|
+
ENV['DATABASE_URL']
|
108
|
+
end
|
109
|
+
|
110
|
+
def db_config_file
|
111
|
+
YAML.load_file(File.join(paths.expanded(:config).first, "database.yml"))
|
100
112
|
end
|
101
113
|
|
102
114
|
def transaction(&block)
|
@@ -161,5 +173,13 @@ module Spontaneous
|
|
161
173
|
return cache_root if path.empty?
|
162
174
|
File.join(cache_root, *path)
|
163
175
|
end
|
176
|
+
|
177
|
+
def development?
|
178
|
+
Spontaneous.development?
|
179
|
+
end
|
180
|
+
|
181
|
+
def inspect
|
182
|
+
%[#<Site @root="#@root" @schema=#{@schema.inspect} @paths=#{@paths.inspect} @environment=#{@environment.inspect} @mode=#{@mode.inspect}>]
|
183
|
+
end
|
164
184
|
end
|
165
185
|
end
|
@@ -20,8 +20,11 @@ class Spontaneous::Site
|
|
20
20
|
module Storage
|
21
21
|
extend Spontaneous::Concern
|
22
22
|
|
23
|
-
|
24
|
-
|
23
|
+
DEFAULT_STORAGE_NAME = 'default'.freeze
|
24
|
+
|
25
|
+
def storage(name = nil)
|
26
|
+
return storage_backends.first if name.nil?
|
27
|
+
storage_backends.detect { |storage| storage.name == name } || default_storage
|
25
28
|
end
|
26
29
|
|
27
30
|
def storage_for_mimetype(mimetype)
|
@@ -40,14 +43,14 @@ class Spontaneous::Site
|
|
40
43
|
storage_backends = []
|
41
44
|
storage_settings = config[:storage] || []
|
42
45
|
storage_settings.each do |name, config|
|
43
|
-
backend = Spontaneous::Media::Store.create(config)
|
46
|
+
backend = Spontaneous::Media::Store.create(name.to_s, config)
|
44
47
|
storage_backends << backend
|
45
48
|
end
|
46
49
|
storage_backends << default_storage
|
47
50
|
end
|
48
51
|
|
49
52
|
def default_storage
|
50
|
-
@default_storage ||= Spontaneous::Media::Store::Local.new(Spontaneous.media_dir, '/media', accepts=nil)
|
53
|
+
@default_storage ||= Spontaneous::Media::Store::Local.new(DEFAULT_STORAGE_NAME, Spontaneous.media_dir, '/media', accepts=nil)
|
51
54
|
end
|
52
55
|
|
53
56
|
def file(owner, filename, headers = {})
|
@@ -18,7 +18,8 @@ module Spontaneous
|
|
18
18
|
options = [
|
19
19
|
"psql",
|
20
20
|
"--quiet",
|
21
|
-
option(:
|
21
|
+
option(:host),
|
22
|
+
option(:port),
|
22
23
|
option(:username),
|
23
24
|
database_name
|
24
25
|
]
|
@@ -42,7 +43,8 @@ module Spontaneous
|
|
42
43
|
"--clean",
|
43
44
|
"--no-owner",
|
44
45
|
"--no-privileges",
|
45
|
-
option(:
|
46
|
+
option(:host),
|
47
|
+
option(:port),
|
46
48
|
option(:username),
|
47
49
|
option(:encoding),
|
48
50
|
option(:exclude_table),
|
@@ -69,6 +71,14 @@ module Spontaneous
|
|
69
71
|
@database.opts[:password]
|
70
72
|
end
|
71
73
|
|
74
|
+
def host
|
75
|
+
@database.opts[:host]
|
76
|
+
end
|
77
|
+
|
78
|
+
def port
|
79
|
+
@database.opts[:port]
|
80
|
+
end
|
81
|
+
|
72
82
|
def encoding
|
73
83
|
"UTF8"
|
74
84
|
end
|
@@ -76,6 +86,17 @@ module Spontaneous
|
|
76
86
|
def exclude_table
|
77
87
|
revision_archive_table
|
78
88
|
end
|
89
|
+
|
90
|
+
def system(cmd)
|
91
|
+
begin
|
92
|
+
if (pass = password)
|
93
|
+
ENV['PGPASSWORD'] = pass
|
94
|
+
end
|
95
|
+
super
|
96
|
+
ensure
|
97
|
+
ENV.delete('PGPASSWORD')
|
98
|
+
end
|
99
|
+
end
|
79
100
|
end
|
80
101
|
end
|
81
102
|
end
|