spontaneous 0.2.0.beta5 → 0.2.0.beta6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (227) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +39 -0
  4. data/Gemfile +2 -0
  5. data/Readme.markdown +4 -4
  6. data/application/css/core.css.scss +144 -43
  7. data/application/css/definitions.css.scss +50 -16
  8. data/application/css/dialogue.css.scss +5 -2
  9. data/application/css/editing.css.scss +7 -7
  10. data/application/css/font.css.scss +1 -1
  11. data/application/css/meta.css.scss +6 -6
  12. data/application/css/popover.css.scss +6 -6
  13. data/application/css/top.css.scss +8 -1
  14. data/application/js/add_alias_dialogue.js +137 -36
  15. data/application/js/add_home_dialogue.js +10 -10
  16. data/application/js/ajax.js +26 -26
  17. data/application/js/authentication.js +2 -2
  18. data/application/js/box.js +21 -10
  19. data/application/js/box_container.js +13 -7
  20. data/application/js/compatibility.js +19 -17
  21. data/application/js/conflicted_field_dialogue.js +5 -5
  22. data/application/js/content.js +22 -16
  23. data/application/js/content_area.js +62 -33
  24. data/application/js/dialogue.js +16 -16
  25. data/application/js/dom.js +9 -10
  26. data/application/js/edit_panel.js +25 -20
  27. data/application/js/editing.js +21 -8
  28. data/application/js/entry.js +1 -1
  29. data/application/js/extensions.js +11 -11
  30. data/application/js/field/boolean.js +6 -6
  31. data/application/js/field/date.js +1 -1
  32. data/application/js/field/file.js +17 -17
  33. data/application/js/field/image.js +27 -27
  34. data/application/js/field/markdown.js +72 -71
  35. data/application/js/field/select.js +9 -9
  36. data/application/js/field/string.js +3 -3
  37. data/application/js/field/webvideo.js +2 -2
  38. data/application/js/field_preview.js +3 -0
  39. data/application/js/init.js +3 -2
  40. data/application/js/jquery-selection-position.js +13 -13
  41. data/application/js/location.js +17 -12
  42. data/application/js/login.js +2 -2
  43. data/application/js/meta_view/user_admin.js +101 -101
  44. data/application/js/metadata.js +1 -1
  45. data/application/js/page.js +2 -2
  46. data/application/js/page_browser.js +13 -13
  47. data/application/js/page_entry.js +1 -1
  48. data/application/js/panel/root_menu.js +10 -10
  49. data/application/js/popover.js +6 -5
  50. data/application/js/popover_view.js +5 -5
  51. data/application/js/preview.js +10 -4
  52. data/application/js/progress.js +6 -6
  53. data/application/js/properties.js +35 -6
  54. data/application/js/publish.js +43 -43
  55. data/application/js/require.js +14 -14
  56. data/application/js/services.js +3 -3
  57. data/application/js/sharded_upload.js +9 -8
  58. data/application/js/side_bar.js +5 -5
  59. data/application/js/state.js +2 -2
  60. data/application/js/status_bar.js +6 -6
  61. data/application/js/top_bar.js +97 -65
  62. data/application/js/types.js +9 -6
  63. data/application/js/upload.js +4 -4
  64. data/application/js/upload_manager.js +21 -21
  65. data/application/js/user.js +1 -1
  66. data/application/js/vendor/jquery.velocity.min.js +7 -0
  67. data/application/js/views.js +32 -8
  68. data/application/js/views/box_view.js +51 -31
  69. data/application/js/views/page_piece_view.js +17 -15
  70. data/application/js/views/page_view.js +54 -43
  71. data/application/js/views/piece_view.js +44 -37
  72. data/application/static/font/fontawesome-webfont-4f0022f25672c7f501c339cbf98d9117.ttf +0 -0
  73. data/application/views/index.erb +1 -0
  74. data/db/migrations/20130114120000_create_revision_tables.rb +2 -1
  75. data/db/migrations/20130813111009_increase_path_length.rb +11 -2
  76. data/db/migrations/20140506171823_add_index_to_target_id.rb +11 -0
  77. data/db/migrations/20140514090204_add_content_hash.rb +59 -0
  78. data/db/migrations/20140519150253_add_content_hash_timestamp.rb +20 -0
  79. data/lib/spontaneous.rb +0 -1
  80. data/lib/spontaneous/asset/environment.rb +77 -15
  81. data/lib/spontaneous/box.rb +21 -0
  82. data/lib/spontaneous/capistrano/deploy.rb +1 -1
  83. data/lib/spontaneous/capistrano/sync.rb +8 -7
  84. data/lib/spontaneous/change.rb +4 -2
  85. data/lib/spontaneous/cli/fields.rb +7 -3
  86. data/lib/spontaneous/cli/generate.rb +2 -0
  87. data/lib/spontaneous/cli/init.rb +24 -93
  88. data/lib/spontaneous/cli/init/db.rb +94 -0
  89. data/lib/spontaneous/cli/init/mysql.rb +17 -0
  90. data/lib/spontaneous/cli/init/postgresql.rb +33 -0
  91. data/lib/spontaneous/cli/init/sqlite.rb +14 -0
  92. data/lib/spontaneous/cli/site.rb +45 -20
  93. data/lib/spontaneous/collections/box_set.rb +3 -0
  94. data/lib/spontaneous/collections/entry_set.rb +43 -4
  95. data/lib/spontaneous/collections/field_set.rb +14 -2
  96. data/lib/spontaneous/data_mapper.rb +40 -7
  97. data/lib/spontaneous/data_mapper/content_model.rb +1 -1
  98. data/lib/spontaneous/data_mapper/content_model/associations.rb +63 -12
  99. data/lib/spontaneous/data_mapper/content_model/timestamps.rb +9 -14
  100. data/lib/spontaneous/data_mapper/content_table.rb +4 -2
  101. data/lib/spontaneous/data_mapper/dataset.rb +31 -2
  102. data/lib/spontaneous/data_mapper/scope.rb +37 -20
  103. data/lib/spontaneous/errors.rb +6 -0
  104. data/lib/spontaneous/facet.rb +20 -10
  105. data/lib/spontaneous/field/base.rb +8 -1
  106. data/lib/spontaneous/field/file.rb +28 -3
  107. data/lib/spontaneous/field/image.rb +2 -0
  108. data/lib/spontaneous/field/update.rb +6 -0
  109. data/lib/spontaneous/field/webvideo/vimeo.rb +6 -1
  110. data/lib/spontaneous/field/webvideo/vine.rb +1 -1
  111. data/lib/spontaneous/field/webvideo/youtube.rb +1 -1
  112. data/lib/spontaneous/generators/site.rb +6 -4
  113. data/lib/spontaneous/generators/site/.gitignore +1 -0
  114. data/lib/spontaneous/generators/site/Gemfile.tt +3 -3
  115. data/lib/spontaneous/generators/site/config/{indexes.rb.tt → initializers/indexes.rb.tt} +0 -0
  116. data/lib/spontaneous/generators/site/config/initializers/publishing.rb.tt +78 -0
  117. data/lib/spontaneous/generators/site/{config/database.yml.tt → db/mysql2.yml.tt} +7 -6
  118. data/lib/spontaneous/generators/site/db/postgres.yml.tt +25 -0
  119. data/lib/spontaneous/generators/site/db/sqlite3.yml.tt +18 -0
  120. data/lib/spontaneous/generators/site/public/humans.txt.tt +14 -0
  121. data/lib/spontaneous/generators/site/templates/layouts/standard.html.cut.tt +51 -0
  122. data/lib/spontaneous/loader.rb +1 -1
  123. data/lib/spontaneous/logger.rb +1 -1
  124. data/lib/spontaneous/media/image/optimizer.rb +1 -1
  125. data/lib/spontaneous/media/image/processor.rb +11 -2
  126. data/lib/spontaneous/media/image/renderable.rb +2 -0
  127. data/lib/spontaneous/model.rb +3 -0
  128. data/lib/spontaneous/model/box/allowed_types.rb +17 -4
  129. data/lib/spontaneous/model/core.rb +36 -3
  130. data/lib/spontaneous/model/core/aliases.rb +5 -2
  131. data/lib/spontaneous/model/core/boxes.rb +6 -0
  132. data/lib/spontaneous/model/core/cascading_change.rb +38 -0
  133. data/lib/spontaneous/model/core/content_hash.rb +171 -0
  134. data/lib/spontaneous/model/core/entries.rb +0 -19
  135. data/lib/spontaneous/model/core/fields.rb +11 -0
  136. data/lib/spontaneous/model/core/modifications.rb +22 -21
  137. data/lib/spontaneous/model/core/render.rb +3 -0
  138. data/lib/spontaneous/model/core/serialisation.rb +18 -17
  139. data/lib/spontaneous/model/page.rb +35 -8
  140. data/lib/spontaneous/model/page/page_tree.rb +20 -8
  141. data/lib/spontaneous/model/page/paths.rb +79 -50
  142. data/lib/spontaneous/model/page/singleton.rb +71 -0
  143. data/lib/spontaneous/model/page/site_map.rb +2 -1
  144. data/lib/spontaneous/model/page/site_timestamps.rb +2 -2
  145. data/lib/spontaneous/model/piece.rb +10 -0
  146. data/lib/spontaneous/output/context.rb +13 -6
  147. data/lib/spontaneous/output/format.rb +30 -5
  148. data/lib/spontaneous/output/helpers/script_helper.rb +8 -0
  149. data/lib/spontaneous/output/helpers/stylesheet_helper.rb +7 -0
  150. data/lib/spontaneous/output/renderable.rb +16 -0
  151. data/lib/spontaneous/output/store.rb +1 -1
  152. data/lib/spontaneous/output/template/renderer.rb +2 -2
  153. data/lib/spontaneous/page_piece.rb +25 -1
  154. data/lib/spontaneous/prototypes/box_prototype.rb +13 -0
  155. data/lib/spontaneous/prototypes/field_prototype.rb +7 -4
  156. data/lib/spontaneous/publishing.rb +10 -5
  157. data/lib/spontaneous/publishing/immediate.rb +32 -349
  158. data/lib/spontaneous/publishing/pipeline.rb +43 -0
  159. data/lib/spontaneous/publishing/progress.rb +186 -0
  160. data/lib/spontaneous/publishing/publish.rb +107 -0
  161. data/lib/spontaneous/publishing/rerender.rb +17 -0
  162. data/lib/spontaneous/publishing/revision.rb +53 -18
  163. data/lib/spontaneous/publishing/simultaneous.rb +1 -1
  164. data/lib/spontaneous/publishing/steps.rb +154 -0
  165. data/lib/spontaneous/publishing/steps/activate_revision.rb +45 -0
  166. data/lib/spontaneous/publishing/steps/archive_old_revisions.rb +22 -0
  167. data/lib/spontaneous/publishing/steps/base_step.rb +49 -0
  168. data/lib/spontaneous/publishing/steps/copy_static_files.rb +74 -0
  169. data/lib/spontaneous/publishing/steps/create_revision_directory.rb +24 -0
  170. data/lib/spontaneous/publishing/steps/generate_rackup_file.rb +51 -0
  171. data/lib/spontaneous/publishing/steps/generate_search_indexes.rb +24 -0
  172. data/lib/spontaneous/publishing/steps/render_revision.rb +69 -0
  173. data/lib/spontaneous/publishing/steps/write_revision_file.rb +43 -0
  174. data/lib/spontaneous/rack/back.rb +3 -1
  175. data/lib/spontaneous/rack/back/alias.rb +9 -8
  176. data/lib/spontaneous/rack/front.rb +1 -1
  177. data/lib/spontaneous/rack/middleware.rb +7 -4
  178. data/lib/spontaneous/rack/middleware/transaction.rb +14 -0
  179. data/lib/spontaneous/rack/page_controller.rb +23 -8
  180. data/lib/spontaneous/revision.rb +5 -10
  181. data/lib/spontaneous/schema.rb +5 -0
  182. data/lib/spontaneous/server.rb +3 -1
  183. data/lib/spontaneous/site.rb +17 -10
  184. data/lib/spontaneous/site/publishing.rb +25 -3
  185. data/lib/spontaneous/site/state.rb +7 -3
  186. data/lib/spontaneous/tasks/database.rake +5 -10
  187. data/lib/spontaneous/utils/database/mysql_dumper.rb +5 -1
  188. data/lib/spontaneous/version.rb +1 -1
  189. data/spontaneous.gemspec +4 -3
  190. data/test/fixtures/example_application/config/initializers/initializer1.rb +1 -0
  191. data/test/fixtures/example_application/config/initializers/initializer2.rb +1 -0
  192. data/test/fixtures/example_application/config/initializers/publishing.rb +13 -0
  193. data/test/fixtures/search/config/{indexes.rb → initializers/indexes.rb} +0 -0
  194. data/test/fixtures/serialisation/root_hash.yaml.erb +10 -4
  195. data/test/functional/test_application.rb +10 -0
  196. data/test/functional/test_back.rb +23 -5
  197. data/test/functional/test_cli.rb +98 -34
  198. data/test/functional/test_front.rb +7 -3
  199. data/test/test_helper.rb +35 -28
  200. data/test/unit/test_alias.rb +20 -3
  201. data/test/unit/test_assets.rb +58 -30
  202. data/test/unit/test_changesets.rb +20 -12
  203. data/test/unit/test_content_hash.rb +496 -0
  204. data/test/unit/test_context.rb +28 -1
  205. data/test/unit/test_controllers.rb +96 -61
  206. data/test/unit/test_crypt.rb +1 -8
  207. data/test/unit/test_datamapper.rb +95 -19
  208. data/test/unit/test_features.rb +1 -4
  209. data/test/unit/test_fields.rb +61 -12
  210. data/test/unit/test_generators.rb +39 -2
  211. data/test/unit/test_images.rb +3 -1
  212. data/test/unit/test_modifications.rb +224 -219
  213. data/test/unit/test_output_store.rb +10 -0
  214. data/test/unit/{test_formats.rb → test_outputs.rb} +75 -6
  215. data/test/unit/test_page.rb +61 -15
  216. data/test/unit/test_plugins.rb +2 -42
  217. data/test/unit/test_publishing_pipeline.rb +1050 -0
  218. data/test/unit/test_render.rb +30 -0
  219. data/test/unit/test_revisions.rb +110 -2
  220. data/test/unit/test_schema.rb +4 -0
  221. data/test/unit/test_search.rb +1 -1
  222. data/test/unit/test_serialisation.rb +6 -1
  223. data/test/unit/test_singletons.rb +159 -0
  224. data/test/unit/test_site.rb +71 -44
  225. metadata +140 -86
  226. data/application/static/font/fontawesome-webfont-1c66a4738b40ef0f6b1abca0ba9a796d.ttf +0 -0
  227. data/test/unit/test_publishing.rb +0 -330
@@ -1,7 +1,17 @@
1
1
  Sequel.migration do
2
+
2
3
  up do
4
+ length = case self.adapter_scheme
5
+ when :mysql, :mysql2
6
+ # http://stackoverflow.com/questions/1814532/1071-specified-key-was-too-long-max-key-length-is-767-bytes/1814594#1814594
7
+ # reasons to move away from mysql...
8
+ 255
9
+ else
10
+ 2048
11
+ end
12
+
3
13
  [:content, :spontaneous_content_archive, :spontaneous_content_history].each do |table|
4
- set_column_type table, :path, 'varchar(2048)'
14
+ set_column_type table, :path, "varchar(#{length})"
5
15
  end
6
16
  end
7
17
 
@@ -11,4 +21,3 @@ Sequel.migration do
11
21
  end
12
22
  end
13
23
  end
14
-
@@ -0,0 +1,11 @@
1
+ # encoding: UTF-8
2
+
3
+ Sequel.migration do
4
+ up do
5
+ add_index :content, :target_id
6
+ end
7
+
8
+ down do
9
+ drop_index :content, :target_id
10
+ end
11
+ end
@@ -0,0 +1,59 @@
1
+ # encoding: UTF-8
2
+
3
+ Sequel.migration do
4
+ up do
5
+ [:content, :spontaneous_content_archive, :spontaneous_content_history].each do |table|
6
+ alter_table table do
7
+ add_column :content_hash, :varchar, size: 32
8
+ add_column :published_content_hash, :varchar, size: 32
9
+ add_column :content_hash_changed, :boolean, default: true
10
+ end
11
+ end
12
+ alter_table :content do
13
+ add_index :content_hash_changed
14
+ end
15
+
16
+ # testing environment
17
+ if defined?(Content)
18
+
19
+ self.logger = nil
20
+
21
+ state = Spontaneous::State.first
22
+
23
+ published_revision = state.nil? ? nil : state[:published_revision]
24
+
25
+ content_hash = published_content_hash = nil
26
+
27
+ model = Spontaneous::Model(:content)
28
+
29
+ update_content_hashes = Proc.new do |content|
30
+ published_content_hash = nil
31
+ content_hash = content.calculate_content_hash!
32
+ if published_revision
33
+ model.mapper.scope(published_revision, false) do
34
+ published = model[content.id]
35
+ published_content_hash = published.calculate_content_hash! if published
36
+ end
37
+ end
38
+ p [content.id, content.class, content.path, content_hash, published_content_hash] #if published_content_hash != content_hash
39
+ model.dataset.unfiltered.where(id: content.id).update(content_hash: content_hash, published_content_hash: published_content_hash, content_hash_changed: (content_hash != published_content_hash))
40
+ end
41
+
42
+ Content::Piece.dataset.order(Sequel.desc(:depth)).each(&update_content_hashes)
43
+ Content::Page.dataset.order(Sequel.desc(:depth)).each(&update_content_hashes)
44
+ end
45
+ end
46
+
47
+ down do
48
+ alter_table :content do
49
+ drop_index :content_hash_changed
50
+ end
51
+ [:spontaneous_content_archive, :spontaneous_content_history].each do |table|
52
+ alter_table table do
53
+ drop_column :content_hash
54
+ drop_column :published_content_hash
55
+ drop_column :content_hash_changed
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+
3
+ Sequel.migration do
4
+ up do
5
+ [:content, :spontaneous_content_archive, :spontaneous_content_history].each do |table|
6
+ alter_table table do
7
+ add_column :content_hash_changed_at, :timestamp
8
+ end
9
+ self[table].update(content_hash_changed_at: :modified_at)
10
+ end
11
+ end
12
+
13
+ down do
14
+ [:content, :spontaneous_content_archive, :spontaneous_content_history].each do |table|
15
+ alter_table table do
16
+ drop_column :content_hash_changed_at
17
+ end
18
+ end
19
+ end
20
+ end
data/lib/spontaneous.rb CHANGED
@@ -108,7 +108,6 @@ module Spontaneous
108
108
  include Plugins::Application::Serialisation
109
109
  include Plugins::Application::Features
110
110
  include Plugins::Application::System
111
- extend Revision::GlobalMethods
112
111
  end
113
112
 
114
113
  Dir["#{File.expand_path("../spontaneous", __FILE__)}/extensions/*.rb"].each { |file| require file }
@@ -5,7 +5,7 @@ module Spontaneous::Asset
5
5
  module Environment
6
6
  def self.new(context)
7
7
  if context.publishing?
8
- Publish.new(context.site, context.revision)
8
+ Publish.new(context.site, context.revision, context.development?)
9
9
  else
10
10
  Preview.new(context.site)
11
11
  end
@@ -42,7 +42,7 @@ module Spontaneous::Asset
42
42
 
43
43
 
44
44
  class Preview
45
- attr_reader :environment
45
+ attr_reader :environment, :site
46
46
 
47
47
  def initialize(site)
48
48
  @site = site
@@ -160,21 +160,88 @@ module Spontaneous::Asset
160
160
  end
161
161
 
162
162
  class Publish < Preview
163
- def initialize(site, revision)
163
+ def initialize(site, revision, development)
164
164
  super(site)
165
- @revision = Spontaneous.revision(revision)
165
+ @revision = site.revision(revision)
166
+ @development = development
167
+ # environment.logger = Logger.new($stdout)
166
168
  environment.css_compressor = :scss
167
169
  environment.js_compressor = :uglifier
168
170
  environment.context_class.manifest = manifest
169
171
  environment.context_class.asset_mount_point = asset_mount_point
170
172
  end
171
173
 
172
- def manifest
173
- @manifest ||= Sprockets::Manifest.new(environment, manifest_file)
174
+ def development?
175
+ @development || false
176
+ end
177
+
178
+ # A proxy to the sprockets manifest that compiles assets on the first run
179
+ # then re-uses them on the second
180
+ class Manifest
181
+ def initialize(environment, revision, development)
182
+ @environment = environment
183
+ @revision = revision
184
+ @development = development || false
185
+ @manifest = Sprockets::Manifest.new(environment.environment, manifest_file)
186
+ end
187
+
188
+ def development?
189
+ @development
190
+ end
191
+
192
+ def manifest_file
193
+ File.join(asset_compilation_dir, "manifest.json")
194
+ end
195
+
196
+ def assets
197
+ @manifest.assets
198
+ end
199
+
200
+ def compile(*args)
201
+ assets = @manifest.assets
202
+ unless (args.all? { |key| assets.key?(key) })
203
+ compile!(*args)
204
+ end
205
+ copy_assets_to_revision(args)
206
+ end
207
+
208
+ def compile!(*args)
209
+ @manifest.compile(*args)
210
+ copy_assets_to_revision(args)
211
+ end
212
+
213
+ def copy_assets_to_revision(logical_paths)
214
+ assets = @manifest.assets
215
+ paths = logical_paths.map { |a| assets[a] }.compact
216
+ source, dest = shared_asset_dir, revision_asset_dir
217
+ paths.each do |asset|
218
+ copy_asset_to_revision(source, dest, asset)
219
+ end
220
+ end
221
+
222
+ def copy_asset_to_revision(source, dest, asset)
223
+ to = dest + asset
224
+ return if to.exist?
225
+ from = source + asset
226
+ to.dirname.mkpath
227
+ FileUtils.cp(from, to)
228
+ end
229
+
230
+ def asset_compilation_dir
231
+ development? ? revision_asset_dir : shared_asset_dir
232
+ end
233
+
234
+ def revision_asset_dir
235
+ @revision.path(@environment.asset_mount_point)
236
+ end
237
+
238
+ def shared_asset_dir
239
+ @environment.site.path!('assets/tmp')
240
+ end
174
241
  end
175
242
 
176
- def manifest_file
177
- File.join(bundle_dir, "manifest.json")
243
+ def manifest
244
+ @manifest ||= Manifest.new(self, @revision, development?)
178
245
  end
179
246
 
180
247
  def find(sources, options)
@@ -189,18 +256,13 @@ module Spontaneous::Asset
189
256
  assets.concat(remote).sort { |a, b| a[1] <=> b[1] }.map(&:first)
190
257
  end
191
258
 
192
- def bundle_dir
193
- @revision.path(asset_mount_point)
194
- end
195
-
196
259
  def to_url(asset)
197
260
  return nil if asset.nil?
198
261
  "/" << asset_mount_point << "/" << asset
199
262
  end
200
263
 
201
264
  def context_extension
202
- Proc.new {
203
-
265
+ Proc.new do
204
266
  class << self
205
267
  attr_accessor :manifest, :asset_mount_point
206
268
  end
@@ -218,7 +280,7 @@ module Spontaneous::Asset
218
280
  def make_absolute(logical)
219
281
  "/" << self.class.asset_mount_point << "/" << logical
220
282
  end
221
- }
283
+ end
222
284
  end
223
285
  end
224
286
  end
@@ -12,6 +12,7 @@ module Spontaneous
12
12
  include Spontaneous::Model::Box::AllowedTypes
13
13
  include Spontaneous::Model::Core::Permissions
14
14
  include Spontaneous::Model::Core::Media
15
+ include Spontaneous::Model::Core::ContentHash::BoxMethods
15
16
 
16
17
  # use underscores to protect against field name conflicts
17
18
  attr_reader :_name, :_prototype, :owner
@@ -79,6 +80,24 @@ module Spontaneous
79
80
  @owner.model
80
81
  end
81
82
 
83
+ # All renderable objects must implement #target to enable aliases & content objects
84
+ # to be treated identically
85
+ def target
86
+ self
87
+ end
88
+
89
+ def renderable
90
+ self
91
+ end
92
+
93
+ def render(format = :html, params = {}, parent_context = nil)
94
+ render_inline(format, params, parent_context)
95
+ end
96
+
97
+ def render_using(renderer, format = :html, params = {}, parent_context = nil)
98
+ render_inline_using(renderer, format, params, parent_context)
99
+ end
100
+
82
101
  def page?
83
102
  false
84
103
  end
@@ -216,6 +235,8 @@ module Spontaneous
216
235
  owner.page
217
236
  end
218
237
 
238
+ alias_method :to_page, :page
239
+
219
240
  def depth
220
241
  owner.content_depth
221
242
  end
@@ -25,7 +25,7 @@ Capistrano::Configuration.instance(:must_exist).load do
25
25
  # Capistrano automatically creates a tmp directory - I don't like that
26
26
  # and would prefer to share tmp between instances
27
27
  task :symlink_tmpdir do
28
- run "cd #{release_path} && rmdir tmp ; ln -nfs #{deploy_to}/shared/tmp ."
28
+ run "cd #{release_path} && rm -r tmp ; ln -nfs #{deploy_to}/shared/tmp ."
29
29
  end
30
30
 
31
31
  task :bundle_assets do
@@ -36,20 +36,21 @@ Capistrano::Configuration.instance(:must_exist).load do
36
36
 
37
37
  desc "Sync the local database to the server version"
38
38
  task :down do
39
- puts "syncing database DOWN"
40
- dumpfilename = ENV['dumpfile'] || "#{Time.now.to_i}.mysql.gz"
39
+ puts " * Syncing database DOWN"
40
+ dumper = Spontaneous::Utils::Database.dumper_for_database
41
+ dumpfilename = ENV['dumpfile'] || dumper.dumpfilename
41
42
  run %(cd #{current_path} && ./bin/rake db:dump dumpfile=#{dumpfilename} )
42
- dump_file = "tmp/#{dumpfilename}"
43
+ dump_file = File.join("tmp", dumpfilename)
43
44
  top.download(File.join(current_path, dump_file), dump_file)
44
45
  system "bundle exec rake db:load dumpfile=#{dump_file}"
45
46
  end
46
47
 
47
48
  desc "Sync the server's version of the database to the local one"
48
49
  task :up do
49
- puts "syncing database UP"
50
- dumpfilename = ENV['dumpfile'] || "#{Time.now.to_i}.mysql.gz"
51
- dump_file = "tmp/#{dumpfilename}"
52
- dumper = ::Spontaneous::Utils::Database.dumper_for_database
50
+ puts " * Syncing database UP"
51
+ dumper = Spontaneous::Utils::Database.dumper_for_database
52
+ dumpfilename = ENV['dumpfile'] || dumper.dumpfilename
53
+ dump_file = File.join("tmp", dumpfilename)
53
54
  dumper.dump(dump_file)
54
55
  remote_dump_file = File.join(deploy_to, dumpfilename)
55
56
  top.upload(dump_file, remote_dump_file)
@@ -15,7 +15,9 @@ module Spontaneous
15
15
  end
16
16
 
17
17
  def unpublished_pages(site)
18
- site.model::Page.filter { (modified_at > last_published_at) | {:first_published_at => nil} }.order(Sequel.desc(:modified_at)).all
18
+ site.model.with_editable { # published content never has changes...
19
+ site.model::Page.filter(content_hash_changed: true).order(Sequel.desc(:content_hash_changed_at)).all
20
+ }
19
21
  end
20
22
 
21
23
  def include_dependencies(page_list)
@@ -90,7 +92,7 @@ module Spontaneous
90
92
  end
91
93
 
92
94
  def modified_at
93
- page.modified_at
95
+ page.content_hash_changed_at
94
96
  end
95
97
 
96
98
  def export_timestamp(timestamp)
@@ -9,7 +9,13 @@ module Spontaneous
9
9
 
10
10
  desc "update", "Performs asynchronous updates on provided fields"
11
11
  method_option :fields, :type => :array, :desc => "List of field IDs to update"
12
- def update
12
+ def update(*args)
13
+ update_fields
14
+ end
15
+
16
+ private
17
+
18
+ def update_fields
13
19
  prepare! :update, :console
14
20
  site = Spontaneous::Site.instance
15
21
  fields = Spontaneous::Field.find(site.model, *options.fields)
@@ -18,8 +24,6 @@ module Spontaneous
18
24
  send_completion_event(updater)
19
25
  end
20
26
 
21
- private
22
-
23
27
  def send_completion_event(updater)
24
28
  unlocked_pages = updater.pages.reject { |p| p.locked_for_update? }
25
29
  simultaneous_event('page_lock_status', unlocked_pages.map(&:id).to_json)
@@ -32,6 +32,8 @@ module Spontaneous::Cli
32
32
  end
33
33
  end
34
34
 
35
+ protected
36
+
35
37
  def generate_site(args)
36
38
  ::Spontaneous::Generators::Site.start(args.drop_while { |e| %w(generate site).include?(e) })
37
39
  end
@@ -19,29 +19,25 @@ module Spontaneous::Cli
19
19
  method_option :create_user, :type => :boolean, :default => true, :desc => "Enable creation of a root user"
20
20
 
21
21
  def init
22
- prepare :init
22
+ initialize_size
23
+ end
23
24
 
24
- site = ::Spontaneous::Site.instantiate(Dir.pwd, options.environment, :console)
25
- Sequel.extension :migration
25
+ protected
26
26
 
27
+ def initialize_size
28
+ prepare :init
27
29
 
28
- database, admin_connection_params, site_connection_params = generate_connection_params
30
+ @site = ::Spontaneous::Site.instantiate(Dir.pwd, options.environment, :console)
31
+ Sequel.extension :migration
29
32
 
30
- [database, "#{database}_test"].each do |db|
31
- config = site_connection_params.merge(:database => db)
32
- create(db, admin_connection_params, config)
33
- migrate(db, site_connection_params, config)
34
- end
33
+ database_initializer.run
35
34
 
36
35
  boot!
37
36
 
38
37
  # Add a root user if this is a new site
39
38
  insert_root_user if (options.create_user && ::Spontaneous::Permissions::User.count == 0)
40
-
41
39
  end
42
40
 
43
- protected
44
-
45
41
  def insert_root_user
46
42
  invoke "user:add", [], options.account
47
43
  # Set up auto_login configuration with the name of the root user
@@ -55,92 +51,27 @@ module Spontaneous::Cli
55
51
  end
56
52
  end
57
53
 
58
- def create(database, admin_config, site_config)
59
- Sequel.connect(admin_config) do |connection|
60
- begin
61
- say " >> Creating database `#{site_config[:database]}`", :green
62
- create_database(connection, site_config)
63
- rescue => e
64
- say " >>> Unable to create #{admin_config[:adapter]} database `#{site_config[:database]}`:\n > #{e}", :red
65
- end
66
- end
54
+ def database_initializer
55
+ @database_initializer ||= get_database_initializer
67
56
  end
68
57
 
69
- def migrate(database, admin_config, site_config)
70
- Sequel.connect(admin_config.merge(:database => site_config[:database])) do |connection|
71
- begin
72
- connection.logger = nil
73
- say " >> Running migrations..."
74
- Sequel::Migrator.apply(connection, ::Spontaneous.gem_dir('db/migrations'))
75
- say " >> Done"
76
- rescue => e
77
- say " >>> Error running migrations on database `#{site_config[:database]}`:\n > #{e}", :red
78
- raise e
79
- end
80
- end
81
- end
82
-
83
- # Converts the site db parameters into 'admin' connection using the provided
84
- # db credentials and the necessary :database settings
85
- def generate_connection_params
86
- site_connection_params = ::Spontaneous.db_settings
87
- connection_params = site_connection_params.dup
88
- connection_params[:user] = options.user unless options.user.blank?
89
- connection_params[:password] = options.password unless options.password.blank?
90
-
91
- database = connection_params.delete(:database)
92
- case connection_params[:adapter]
58
+ def get_database_initializer
59
+ connection_params = @site.db_config
60
+ classname = case connection_params[:development][:adapter]
93
61
  when /mysql/
62
+ 'MySQL'
94
63
  when /postgres/
95
- # postgres requires that you connect to a db.
96
- # "postgres" is guaranteed to exist
97
- connection_params[:database] = "postgres"
98
- end
99
- [database, connection_params, site_connection_params]
100
- end
101
-
102
- def create_database(connection, config)
103
- commands = case connection.database_type
104
- when :postgres
105
- create_postgres_database_commands(config)
106
- when :mysql
107
- create_mysql_database_commands(config)
108
- end
109
- commands.each do |command, raise_error|
110
- begin
111
- connection.run(command)
112
- rescue => e
113
- raise e if raise_error
114
- end
115
- end
116
- end
117
-
118
- def create_mysql_database_commands(config)
119
- host = config[:host].blank? ? "" : "@#{config[:host]}"
120
- cmds = [ ["CREATE DATABASE `#{config[:database]}` CHARACTER SET UTF8", true] ]
121
- unless config[:user] == "root"
122
- cmds << ["GRANT ALL ON `#{config[:database]}`.* TO `#{config[:user]}`#{host} IDENTIFIED BY '#{config[:password]}'", false]
123
- end
124
- cmds
125
- end
126
-
127
- # On some machines the db creation fails due to incompabilities between the UTF8 encoding
128
- # and the configured locale.
129
- # You can force a locale for the db by adding LC_COLLATE & LC_CTYPE params
130
- # to the CREATE command:
131
- #
132
- # LC_COLLATE='C.UTF-8' LC_CTYPE='C.UTF-8'
133
- #
134
- # but I don't know a good/the best way to determine the most appropriate UTF-8 locale
135
- # C.UTF-8 doesn't exist on OS X.
136
- def create_postgres_database_commands(config)
137
- create_cmd = %(CREATE DATABASE "#{config[:database]}" WITH TEMPLATE=template0 ENCODING='UTF8')
138
- cmds = []
139
- unless config[:user].blank?
140
- create_cmd << %( OWNER="#{config[:user]}")
141
- cmds << [%(CREATE ROLE "#{config[:user]}" LOGIN PASSWORD '#{config[:password]}'), false]
64
+ 'Postgresql'
65
+ when /sqlite/
66
+ 'Sqlite'
142
67
  end
143
- cmds << [create_cmd, true]
68
+ klass = Spontaneous::Cli::Init.const_get(classname)
69
+ klass.new(connection_params, self)
144
70
  end
145
71
  end # Init
146
72
  end # Spontaneous::Cli
73
+
74
+ require 'spontaneous/cli/init/db'
75
+ require 'spontaneous/cli/init/postgresql'
76
+ require 'spontaneous/cli/init/mysql'
77
+ require 'spontaneous/cli/init/sqlite'