Pimki 1.0.092

Sign up to get free protection for your applications and to get access to all the features.
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