spontaneous 0.2.0.beta9 → 0.2.0.beta10
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 +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
|