Pimki 1.0.092

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.
Files changed (85) hide show
  1. data/README +158 -0
  2. data/README-PIMKI +87 -0
  3. data/app/controllers/wiki.rb +563 -0
  4. data/app/models/author.rb +4 -0
  5. data/app/models/chunks/category.rb +31 -0
  6. data/app/models/chunks/category_test.rb +21 -0
  7. data/app/models/chunks/chunk.rb +20 -0
  8. data/app/models/chunks/engines.rb +34 -0
  9. data/app/models/chunks/include.rb +29 -0
  10. data/app/models/chunks/literal.rb +19 -0
  11. data/app/models/chunks/match.rb +19 -0
  12. data/app/models/chunks/nowiki.rb +31 -0
  13. data/app/models/chunks/nowiki_test.rb +14 -0
  14. data/app/models/chunks/test.rb +18 -0
  15. data/app/models/chunks/todo.rb +22 -0
  16. data/app/models/chunks/uri.rb +97 -0
  17. data/app/models/chunks/uri_test.rb +92 -0
  18. data/app/models/chunks/wiki.rb +82 -0
  19. data/app/models/chunks/wiki_test.rb +36 -0
  20. data/app/models/page.rb +91 -0
  21. data/app/models/page_lock.rb +24 -0
  22. data/app/models/page_set.rb +73 -0
  23. data/app/models/page_test.rb +76 -0
  24. data/app/models/revision.rb +91 -0
  25. data/app/models/revision_test.rb +252 -0
  26. data/app/models/web.rb +277 -0
  27. data/app/models/web_test.rb +53 -0
  28. data/app/models/wiki_content.rb +113 -0
  29. data/app/models/wiki_service.rb +137 -0
  30. data/app/models/wiki_service_test.rb +15 -0
  31. data/app/models/wiki_words.rb +26 -0
  32. data/app/models/wiki_words_test.rb +12 -0
  33. data/app/views/bottom.rhtml +4 -0
  34. data/app/views/markdown_help.rhtml +16 -0
  35. data/app/views/menu.rhtml +20 -0
  36. data/app/views/navigation.rhtml +26 -0
  37. data/app/views/rdoc_help.rhtml +16 -0
  38. data/app/views/static_style_sheet.rhtml +231 -0
  39. data/app/views/style.rhtml +179 -0
  40. data/app/views/textile_help.rhtml +28 -0
  41. data/app/views/top.rhtml +52 -0
  42. data/app/views/wiki/authors.rhtml +15 -0
  43. data/app/views/wiki/bliki.rhtml +101 -0
  44. data/app/views/wiki/bliki_edit.rhtml +33 -0
  45. data/app/views/wiki/bliki_new.rhtml +61 -0
  46. data/app/views/wiki/bliki_revision.rhtml +51 -0
  47. data/app/views/wiki/edit.rhtml +34 -0
  48. data/app/views/wiki/edit_menu.rhtml +27 -0
  49. data/app/views/wiki/edit_web.rhtml +139 -0
  50. data/app/views/wiki/export.rhtml +14 -0
  51. data/app/views/wiki/feeds.rhtml +10 -0
  52. data/app/views/wiki/list.rhtml +164 -0
  53. data/app/views/wiki/locked.rhtml +14 -0
  54. data/app/views/wiki/login.rhtml +11 -0
  55. data/app/views/wiki/mind.rhtml +39 -0
  56. data/app/views/wiki/new.rhtml +27 -0
  57. data/app/views/wiki/new_system.rhtml +78 -0
  58. data/app/views/wiki/new_web.rhtml +64 -0
  59. data/app/views/wiki/page.rhtml +84 -0
  60. data/app/views/wiki/print.rhtml +16 -0
  61. data/app/views/wiki/published.rhtml +10 -0
  62. data/app/views/wiki/recently_revised.rhtml +31 -0
  63. data/app/views/wiki/revision.rhtml +87 -0
  64. data/app/views/wiki/rss_feed.rhtml +22 -0
  65. data/app/views/wiki/search.rhtml +26 -0
  66. data/app/views/wiki/tex.rhtml +23 -0
  67. data/app/views/wiki/tex_web.rhtml +35 -0
  68. data/app/views/wiki/todo.rhtml +39 -0
  69. data/app/views/wiki/web_list.rhtml +13 -0
  70. data/app/views/wiki_words_help.rhtml +8 -0
  71. data/libraries/action_controller_servlet.rb +177 -0
  72. data/libraries/bluecloth.rb +1127 -0
  73. data/libraries/diff/diff.rb +475 -0
  74. data/libraries/diff/diff_test.rb +80 -0
  75. data/libraries/erb.rb +490 -0
  76. data/libraries/madeleine/automatic.rb +357 -0
  77. data/libraries/madeleine/clock.rb +94 -0
  78. data/libraries/madeleine_service.rb +69 -0
  79. data/libraries/rdocsupport.rb +156 -0
  80. data/libraries/redcloth_for_tex.rb +869 -0
  81. data/libraries/redcloth_for_tex_test.rb +41 -0
  82. data/libraries/view_helper.rb +33 -0
  83. data/libraries/web_controller_server.rb +95 -0
  84. data/pimki.rb +97 -0
  85. metadata +169 -0
@@ -0,0 +1,357 @@
1
+ require 'yaml'
2
+
3
+ module Madeleine
4
+
5
+ # Automatic commands for Madeleine
6
+ #
7
+ # Author:: Stephen Sykes <ruby@stephensykes.com>
8
+ # Copyright:: Copyright (C) 2003-2004
9
+ # Version:: 0.4
10
+ #
11
+ # This module provides a way of automatically generating command objects for madeleine to
12
+ # store. It works by making a proxy object for all objects of any classes in which it is included.
13
+ # Method calls to these objects are intercepted, and stored as a command before being
14
+ # passed on to the real receiver. The command objects remember which object the command was
15
+ # destined for by using a pair of internal ids that are contained in each of the proxy objects.
16
+ #
17
+ # There is also a mechanism for specifying which methods not to intercept calls to by using
18
+ # automatic_read_only, and its opposite automatic_read_write.
19
+ #
20
+ # Should you require it, the snapshots can be stored as yaml, just pass YAML as the second
21
+ # argument to AutomaticSnapshotMadeleine.new. The system will read either Marshal or YAML at
22
+ # startup.
23
+ #
24
+ # This module is designed to work correctly in the case there are multiple madeleine systems in use by
25
+ # a single program, and is also safe to use with threads.
26
+ #
27
+ # Usage:
28
+ #
29
+ # require 'madeleine'
30
+ # require 'madeleine/automatic'
31
+ #
32
+ # class A
33
+ # include Madeleine::Automatic::Interceptor
34
+ # attr_reader :foo
35
+ # automatic_read_only :foo
36
+ # def initialize(param1, ...)
37
+ # ...
38
+ # end
39
+ # def some_method(paramA, ...)
40
+ # ...
41
+ # end
42
+ # automatic_read_only
43
+ # def bigfoo
44
+ # foo.upcase
45
+ # end
46
+ # end
47
+ #
48
+ # mad = AutomaticSnapshotMadeleine.new("storage_directory") { A.new(param1, ...) }
49
+ #
50
+ # mad.system.some_method(paramA, ...) # logged as a command by madeleine
51
+ # print mad.foo # not logged
52
+ # print mad.bigfoo # not logged
53
+ # mad.take_snapshot
54
+ #
55
+
56
+ module Automatic
57
+ #
58
+ # This module should be included (at the top) in any classes that are to be persisted.
59
+ # It will intercept method calls and make sure they are converted into commands that are logged by Madeleine.
60
+ # It does this by returning a Prox object that is a proxy for the real object.
61
+ #
62
+ # It also handles automatic_read_only and automatic_read_write, allowing user specification of which methods
63
+ # should be made into commands
64
+ #
65
+ module Interceptor
66
+ #
67
+ # When included, redefine new so that we can return a Prox object instead, and define methods to handle
68
+ # keeping track of which methods are read only
69
+ #
70
+ def self.included(klass)
71
+ class << klass #:nodoc:
72
+ alias_method :_old_new, :new
73
+ @@auto_read_only_flag = false
74
+ @@read_only_methods = []
75
+
76
+ def new(*args, &block)
77
+ Prox.new(_old_new(*args, &block))
78
+ end
79
+ #
80
+ # Called when a method added - remember symbol if read only
81
+ #
82
+ def method_added(symbol)
83
+ @@read_only_methods << symbol if @@auto_read_only_flag
84
+ end
85
+ #
86
+ # Set the read only flag, or add read only methods
87
+ #
88
+ def automatic_read_only(*list)
89
+ if (list == [])
90
+ @@auto_read_only_flag = true
91
+ else
92
+ list.each {|s| @@read_only_methods << s}
93
+ end
94
+ end
95
+ #
96
+ # Clear the read only flag, or remove read only methods
97
+ #
98
+ def automatic_read_write(*list)
99
+ if (list == [])
100
+ @@auto_read_only_flag = false
101
+ else
102
+ list.each {|s| @@read_only_methods.delete(s)}
103
+ end
104
+ end
105
+
106
+ end
107
+ end
108
+ #
109
+ # Return the list of read only methods so Prox#method_missing can find what to and what not to make into a command
110
+ #
111
+ def read_only_methods
112
+ @@read_only_methods
113
+ end
114
+ end
115
+
116
+ #
117
+ # A Command object is automatically created for each method call to an object within the system that comes from without.
118
+ # These objects are recorded in the log by Madeleine.
119
+ #
120
+ # Note: The command also records which system it belongs to. This is used in a recovery situation.
121
+ # If a command contains a sysid that doesn't match the system sent to us, then we change that
122
+ # system's id to the one in the command. This makes a system adopt the correct id as soon as a
123
+ # command for it is executed. This is the case when restoring a system for which there is no snapshot.
124
+ #
125
+ class Command
126
+ def initialize(symbol, myid, sysid, *args)
127
+ @symbol = symbol
128
+ @myid = myid
129
+ @sysid = sysid
130
+ @args = args
131
+ end
132
+ #
133
+ # Called by madeleine when the command is done either first time, or when restoring the log
134
+ #
135
+ def execute(system)
136
+ AutomaticSnapshotMadeleine.register_sysid(@sysid) if (system.sysid != @sysid)
137
+ Thread.current[:system].myid2ref(@myid).thing.send(@symbol, *@args)
138
+ end
139
+ end
140
+ #
141
+ # This is a little class to pass to SnapshotMadeleine. This is used for snapshots only.
142
+ # It acts as the marshaller, and just passes marshalling requests on to the user specified
143
+ # marshaller. This defaults to Marshal, but could be YAML or another.
144
+ # After we have done a restore, the ObjectSpace is searched for instances of Prox to
145
+ # add new objects to the list in AutomaticSnapshotMadeleine
146
+ #
147
+ class Automatic_marshaller
148
+ def Automatic_marshaller.load(io)
149
+ # restored_obj = Thread.current[:system].marshaller.load(arg)
150
+ restored_obj = Deserialize.load(io, Thread.current[:system].marshaller)
151
+ ObjectSpace.each_object(Prox) {|o| Thread.current[:system].restore(o) if (o.sysid == restored_obj.sysid)}
152
+ restored_obj
153
+ end
154
+ def Automatic_marshaller.dump(obj, stream = nil)
155
+ Thread.current[:system].marshaller.dump(obj, stream)
156
+ end
157
+ end
158
+ #
159
+ # A Prox object is generated and returned by Interceptor each time a system object is created.
160
+ #
161
+ class Prox
162
+ attr_accessor :thing, :myid, :sysid
163
+
164
+ def initialize(thing)
165
+ if (thing)
166
+ raise "App object created outside of app" unless Thread.current[:system]
167
+ @sysid = Thread.current[:system].sysid
168
+ @myid = Thread.current[:system].add(self)
169
+ @thing = thing
170
+ end
171
+ end
172
+ #
173
+ # This automatically makes and executes a new Command if a method is called from
174
+ # outside the system.
175
+ #
176
+ def method_missing(symbol, *args, &block)
177
+ # print "Sending #{symbol} to #{@thing.to_s}, myid=#{@myid}, sysid=#{@sysid}\n"
178
+ raise NoMethodError, "Undefined method" unless @thing.respond_to?(symbol)
179
+ if (Thread.current[:system] || @thing.read_only_methods.include?(symbol))
180
+ @thing.send(symbol, *args, &block)
181
+ else
182
+ raise "Cannot make command with block" if block_given?
183
+ Thread.current[:system] = AutomaticSnapshotMadeleine.systems[@sysid]
184
+ begin
185
+ result = Thread.current[:system].execute_command(Command.new(symbol, @myid, @sysid, *args))
186
+ ensure
187
+ Thread.current[:system] = false
188
+ end
189
+ result
190
+ end
191
+ end
192
+ #
193
+ # Custom marshalling - this adds the internal id (myid) and the system id to a marshall
194
+ # of the object we are the proxy for.
195
+ # We take care to not marshal the same object twice, so circular references will work.
196
+ # We ignore Thread.current[:system].marshaller here - this is only called by Marshal, and
197
+ # marshal is always used for Command objects
198
+ #
199
+ def _dump(depth)
200
+ if (Thread.current[:snapshot_memory])
201
+ if (Thread.current[:snapshot_memory][self])
202
+ [@myid.to_s, @sysid].pack("A8A30")
203
+ else
204
+ Thread.current[:snapshot_memory][self] = true
205
+ [@myid.to_s, @sysid].pack("A8A30") + Marshal.dump(@thing, depth)
206
+ end
207
+ else
208
+ [@myid.to_s, @sysid].pack("A8A30")
209
+ end
210
+ end
211
+ #
212
+ # Custom marshalling for Marshal - restore a Prox object.
213
+ #
214
+ def Prox._load(str)
215
+ x = Prox.new(nil)
216
+ a = str.unpack("A8A30a*")
217
+ x.myid = a[0].to_i
218
+ x.sysid = a[1]
219
+ x = Thread.current[:system].restore(x)
220
+ x.thing = Marshal.load(a[2]) if (a[2] > "")
221
+ x
222
+ end
223
+
224
+ end
225
+
226
+ #
227
+ # The AutomaticSnapshotMadeleine class contains an instance of the persister
228
+ # (default is SnapshotMadeleine) and provides additional automatic functionality.
229
+ #
230
+ # The class keeps a record of all the systems that currently exist.
231
+ # Each instance of the class keeps a record of Prox objects in that system by internal id (myid).
232
+ #
233
+ # We also add functionality to take_snapshot in order to set things up so that the custom Prox object
234
+ # marshalling will work correctly.
235
+ #
236
+ class AutomaticSnapshotMadeleine
237
+ attr_accessor :sysid, :marshaller
238
+ attr_reader :list, :marshaller
239
+
240
+ def initialize(directory_name, marshaller=Marshal, persister=SnapshotMadeleine, &new_system_block)
241
+ @sysid ||= Time.now.to_f.to_s + Thread.current.object_id.to_s # Gererate a new sysid
242
+ @myid_count = 0 # This sysid will be used only if new
243
+ @list = {} # object is taken by madeleine
244
+ Thread.current[:system] = self # during system startup system should not create commands
245
+ AutomaticSnapshotMadeleine.register_sysid(@sysid) # this sysid may be overridden
246
+ @marshaller = marshaller # until attrb
247
+ begin
248
+ @persister = persister.new(directory_name, Automatic_marshaller, &new_system_block)
249
+ AutomaticSnapshotMadeleine.register_sysid(@sysid) # needed if there were no commands
250
+ ensure
251
+ Thread.current[:system] = false
252
+ end
253
+ end
254
+ #
255
+ # Add a proxy object to the list, return the myid for that object
256
+ #
257
+ def add(proxo)
258
+ @list[@myid_count += 1] = proxo.object_id
259
+ @myid_count
260
+ end
261
+ #
262
+ # Restore a marshalled proxy object to list - myid_count is increased as required.
263
+ # If the object already exists in the system then the existing object must be used.
264
+ #
265
+ def restore(proxo)
266
+ if (@list[proxo.myid])# && proxo.sysid == myid2ref(proxo.myid).sysid)
267
+ proxo = myid2ref(proxo.myid)
268
+ else
269
+ @list[proxo.myid] = proxo.object_id
270
+ @myid_count = proxo.myid if (@myid_count < proxo.myid)
271
+ end
272
+ @sysid = proxo.sysid # to be sure to have the correct sysid
273
+ proxo
274
+ end
275
+ #
276
+ # Returns a reference to the object indicated by the internal id supplied.
277
+ #
278
+ def myid2ref(myid)
279
+ raise "Internal id #{myid} not found" unless objid = @list[myid]
280
+ ObjectSpace._id2ref(objid)
281
+ end
282
+ #
283
+ # Take a snapshot of the system.
284
+ #
285
+ def take_snapshot
286
+ begin
287
+ Thread.current[:system] = self
288
+ Thread.current[:snapshot_memory] = {}
289
+ @persister.take_snapshot
290
+ ensure
291
+ Thread.current[:snapshot_memory] = nil
292
+ Thread.current[:system] = false
293
+ end
294
+ end
295
+ #
296
+ # Sets the real sid for this thread's system - called during startup or from a command.
297
+ #
298
+ def AutomaticSnapshotMadeleine.register_sysid(sid)
299
+ Thread.critical = true
300
+ @@systems ||= {} # holds systems by sysid
301
+ @@systems[sid] = Thread.current[:system]
302
+ Thread.critical = false
303
+ @@systems[sid].sysid = sid
304
+ @@systems[sid].list.delete_if {|k,v| # set all the prox objects that already exist to have the right sysid
305
+ begin
306
+ ObjectSpace._id2ref(v).sysid = sid
307
+ false
308
+ rescue RangeError
309
+ true # Id was to a GC'd object, delete it
310
+ end
311
+ }
312
+ end
313
+ #
314
+ # Returns the hash containing the systems.
315
+ #
316
+ def AutomaticSnapshotMadeleine.systems
317
+ @@systems
318
+ end
319
+ #
320
+ # Pass on any other calls to the persister
321
+ #
322
+ def method_missing(symbol, *args, &block)
323
+ @persister.send(symbol, *args, &block)
324
+ end
325
+ end
326
+
327
+
328
+ class Deserialize
329
+ #
330
+ # Detect marshal format, and return deserialized object using the right marshaller
331
+ # If detection didn't work, use the marshaller given in the optional 2nd argument
332
+ #
333
+ def Deserialize.load(io, marshaller=Marshal)
334
+ c = io.getc
335
+ c1 = io.getc
336
+ io.rewind
337
+ if (c == Marshal::MAJOR_VERSION && c1 <= Marshal::MINOR_VERSION)
338
+ Marshal.load(io)
339
+ else
340
+ while (s = io.gets)
341
+ break if (s !~ /^\s*#/ && s !~ /^\s*$/) # ignore blank and comment lines
342
+ end
343
+ io.rewind
344
+ if (s && s =~ /^\s*---/) # "---" is the yaml header
345
+ YAML.load(io)
346
+ else
347
+ marshaller.load(io)
348
+ end
349
+ end
350
+ end
351
+
352
+ end
353
+
354
+ end
355
+ end
356
+
357
+ AutomaticSnapshotMadeleine = Madeleine::Automatic::AutomaticSnapshotMadeleine
@@ -0,0 +1,94 @@
1
+ #
2
+ # Copyright(c) Anders Bengtsson 2003
3
+ #
4
+
5
+ require 'madeleine'
6
+
7
+ module Madeleine
8
+ module Clock
9
+
10
+ # Deprecated. Use SnapshotMadeleine instead.
11
+ class ClockedSnapshotMadeleine < ::Madeleine::SnapshotMadeleine
12
+ end
13
+
14
+ # Let your system extend this module if you need to access the
15
+ # machine time. Used together with a TimeActor that keeps
16
+ # the clock current.
17
+ module ClockedSystem
18
+
19
+ # Returns this system's Clock.
20
+ def clock
21
+ unless defined? @clock
22
+ @clock = Clock.new
23
+ end
24
+ @clock
25
+ end
26
+ end
27
+
28
+ # Sends clock ticks to update a ClockedSystem, so that time can be
29
+ # dealt with in a deterministic way.
30
+ class TimeActor
31
+
32
+ # Create and launch a new TimeActor
33
+ #
34
+ # * <tt>madeleine</tt> - The SnapshotMadeleine instance to work on.
35
+ # * <tt>delay</tt> - Delay between ticks in seconds (Optional).
36
+ def self.launch(madeleine, delay=0.1)
37
+ result = new(madeleine, delay)
38
+ result
39
+ end
40
+
41
+ # Stops the TimeActor.
42
+ def destroy
43
+ @is_destroyed = true
44
+ @thread.wakeup
45
+ @thread.join
46
+ end
47
+
48
+ private_class_method :new
49
+
50
+ private
51
+
52
+ def initialize(madeleine, delay) #:nodoc:
53
+ @madeleine = madeleine
54
+ @is_destroyed = false
55
+ send_tick
56
+ @thread = Thread.new {
57
+ until @is_destroyed
58
+ sleep(delay)
59
+ send_tick
60
+ end
61
+ }
62
+ end
63
+
64
+ def send_tick
65
+ @madeleine.execute_command(Tick.new(Time.now))
66
+ end
67
+ end
68
+
69
+ # Keeps track of time in a ClockedSystem.
70
+ class Clock
71
+ # Returns the system's time as a Ruby <tt>Time</tt>.
72
+ attr_reader :time
73
+
74
+ def initialize
75
+ @time = Time.at(0)
76
+ end
77
+
78
+ def forward_to(newTime)
79
+ @time = newTime
80
+ end
81
+ end
82
+
83
+ #
84
+ # Internal classes below
85
+ #
86
+
87
+ # Deprecated. Merged into default implementation.
88
+ class TimeOptimizingLogger < ::Madeleine::Logger
89
+ end
90
+
91
+ end
92
+ end
93
+
94
+ ClockedSnapshotMadeleine = Madeleine::Clock::ClockedSnapshotMadeleine