clwiki 2.4.0 → 3.0.4

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 (289) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +19 -9
  3. data/app/controllers/cl_wiki/application_controller.rb +34 -1
  4. data/app/controllers/cl_wiki/page_controller.rb +53 -38
  5. data/app/controllers/cl_wiki/sessions_controller.rb +41 -0
  6. data/app/helpers/cl_wiki/application_helper.rb +3 -1
  7. data/app/models/cl_wiki/user.rb +89 -0
  8. data/app/views/cl_wiki/page/edit.html.erb +5 -1
  9. data/app/views/cl_wiki/page/recent.html.erb +1 -1
  10. data/app/views/cl_wiki/page/recent.rss.builder +10 -8
  11. data/app/views/cl_wiki/sessions/new.html.erb +10 -0
  12. data/config/clwiki.yml +16 -30
  13. data/config/initializers/clwiki.rb +4 -3
  14. data/config/routes.rb +9 -0
  15. data/lib/cl_wiki.rb +5 -1
  16. data/lib/cl_wiki/configuration.rb +28 -137
  17. data/lib/cl_wiki/engine.rb +3 -1
  18. data/lib/cl_wiki/file.rb +136 -118
  19. data/lib/cl_wiki/format/format.blockquote.rb +8 -6
  20. data/lib/cl_wiki/format/format.graphviz.digraph.rb +8 -7
  21. data/lib/cl_wiki/format/format.opml.rb +11 -9
  22. data/lib/cl_wiki/format/format.pre.blockquote.rb +8 -6
  23. data/lib/cl_wiki/format/format.simpletable.rb +10 -8
  24. data/lib/cl_wiki/memory_index.rb +102 -0
  25. data/lib/cl_wiki/page.rb +129 -257
  26. data/lib/cl_wiki/public_user.rb +9 -0
  27. data/lib/cl_wiki/user_base.rb +25 -0
  28. data/lib/cl_wiki/version.rb +3 -1
  29. data/lib/cl_wiki_lib.rb +9 -0
  30. data/lib/tasks/index.rake +4 -4
  31. data/test/dummy/app/assets/config/manifest.js +3 -0
  32. data/test/dummy/config/application.rb +1 -0
  33. data/test/dummy/config/environments/development.rb +2 -0
  34. data/test/dummy/config/initializers/clwiki.rb +3 -0
  35. data/test/dummy/config/routes.rb +3 -0
  36. data/test/dummy/log/development.log +5909 -0
  37. data/test/dummy/log/test.log +40450 -0
  38. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/-8/-8X-3n5w3EAS5uiBS2GQxjMlqD43Qout1GsSJUU6e4k.cache +1 -0
  39. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/-P/-Pa1BPD1Ps1OvnKPyrGE4MiUEnlzMEccXN8CzzxSRjM.cache +1 -0
  40. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/0D/0DBWc4mmZE_dxtKcI5zwuwFah928eWto3S4tV-h1qUY.cache +1 -0
  41. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/0k/0ktSefuSiZXp-1v5uXwST57lRoAF2HvHzclO4Gtftgo.cache +2 -0
  42. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/1V/1VmPI9-8O9Y8OP-JxSXl7-yNRMZHqapeh2drmkXiRGE.cache +1 -0
  43. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/28/28R8437OhGS51UlWKpnAZIJ3qJWxLaA1BJtFIEjW9aw.cache +0 -0
  44. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/2W/2WKPDryRtGzZO6Uedw4RNjnI5M9YVH-IbFg5GvLvTTQ.cache +0 -0
  45. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/2v/2vD9gOomeGZ1sPMc23Aqsbr95WAu7fDeShhuZuf62cY.cache +1 -0
  46. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/3G/3GuA3P7RM10Vv7NgdH65pwfAH7gMHlJ_xBUO74i-ZjM.cache +0 -0
  47. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/3S/3SzCkB81tc9XbtFdEYxCeR3If141gvhEnHchU_C6hHs.cache +1 -0
  48. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/41/41dY2GtQJAt3CmkQn8IDa9B3clQaUT6XymanCfFZR2o.cache +0 -0
  49. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/46/46WEPovJzlkEgsdG0aV08HiNsRkf0L8Txt1SWLi4atg.cache +1 -0
  50. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/4I/4Ir0PJhTRUd9iGlSu6n2AREP-_amedFe4-1fKwB2wvg.cache +1 -0
  51. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/5L/5LXSsjTcB5Un8FHlrhi6AOjxwgzWoXeWBhU_hi1gdcg.cache +1 -0
  52. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/67/67V_0cxwrU68Onen7N2Lb9bTd1jLulH06F9zh1VgZ0U.cache +1 -0
  53. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/6A/6AXD3XLczHK8MPb5e10-7sLcS45ZrP7Iwgyo9xle0nU.cache +0 -0
  54. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/6D/6D8TdXG6KyMkGDvPbv87qUCDz9_6gRZbNAohojB484w.cache +1 -0
  55. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7L/7LVfTxjfHpOSp2FeG-uhloqIUqIZ7uE3nT40dqhoqY8.cache +2 -0
  56. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7b/7bceaEE3qsyoVjeou6RR-V9w2Wgzraq0OI2erU4s9ew.cache +1 -0
  57. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7h/7hRfgp9EsoD33qh0aNXeyg9qdGapPlUT6FmcL8xztY4.cache +0 -0
  58. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8c/8cq-JtJ9Zwg4F0bFdkqaGHjdB7a9JBmfDO_sczTWycI.cache +1 -0
  59. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8d/8d2c1LpTZA9uuWml5O7SZIziW2o693h9gykizTBPBqw.cache +0 -0
  60. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8h/8hO7EIQ5iOa2rL6ZlP318Lrk0unB2CfhHCI0TrUr-Oo.cache +0 -0
  61. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8x/8x0PXM3vatUzVGk-vKi80S7LXrGb6bE-3EzEj54VNak.cache +1 -0
  62. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/92/92txvq5_0oqyi4tKR-CTpu_hucsOQk4gSa_Soq_XIlc.cache +0 -0
  63. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/95/9501Slgi11UyN1aBXNCu4pxOpaRKyBcmSmiqPPJanmw.cache +0 -0
  64. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/9v/9vfh8eoLcnq3s_rolIXPs15SPTQWGxJrrjpJ3PoABek.cache +1 -0
  65. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/9w/9w-0hdVYmxONDHQlpGn7DFzlRA3oXqpW4x3t9LBUU6M.cache +1 -0
  66. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/B3/B385Es3x0hpGSQNWzSjiDcExPuEV9m1dUZWlEp5zGbw.cache +0 -0
  67. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/BR/BRBOvy22uVEx9Z5Aal_0BfPilVYEQl6AYXG2u8yBqBg.cache +0 -0
  68. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/BX/BXdNycvZI2UN7cgqvk6P4MQCc1PH2bTwa9i9vP-s-jk.cache +0 -0
  69. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/CA/CA9tJ74jTtOpYcNWZPrQLc26SkJdAu1BLuwFsWqiFX0.cache +0 -0
  70. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/CO/CO-z80mMyQGRy-BwknxOV5bI2IFbcMMNc05j7v8Nqso.cache +0 -0
  71. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/CY/CYGZRzrr6e2EOdwxmPLy_tYjneXGrr_uhTMALX2jyGY.cache +1 -0
  72. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Cg/CgPqTXtSkCxEox0z95JfY89MndA2GhTTQK39fjKk6QU.cache +1 -0
  73. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ct/CtQeoxqXfctXd_NvChnCVaJ_cCjNuXJMv3LBXhswU6A.cache +0 -0
  74. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Dc/DcZ_YfpX7rLYFw-u7jSJCRp_z0iIyB7XKOcwm1cQexk.cache +0 -0
  75. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ex/Exqg59Ton1SZt_QH4hMa7wUFOAuIQnCan8B9578NzIg.cache +0 -0
  76. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/F5/F5c-QANC5X3kApAecuyiMZEme0NT_UUB6SjxKvb0ALg.cache +1 -0
  77. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Fd/FdwPBPhLtL4s8RSPhJ53YoYoFdRkNxANV_zQYw-KsVc.cache +1 -0
  78. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Fz/FzgTyTGCIlSZyXn77nSzsYhiD2AFBrNiMOwNeBtmV8Y.cache +0 -0
  79. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/GK/GKrbCoxDofzkQCmA17lE84OT6RW_6NKm7jwyZ4n2T6s.cache +0 -0
  80. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Gh/GhVuWwPtbWpQY_Ny4MyilnH9iUqCPxTDzOonAXM4od8.cache +1 -0
  81. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Gv/GvQrSgGYXiR-rgsPHFZq1oJ5zCkDK54muqIw6KW2GyA.cache +0 -0
  82. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Gw/Gwhhfk9vS7QWmHsW90WtAt0_Rp_7AIM-ZcHmEqLf_Rg.cache +1 -0
  83. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/H5/H5Yxi2VJxpyMb-cbgwBNua8O2zZ03Jk4ByV6yhIzAsQ.cache +0 -0
  84. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/I0/I0OpFIfCc595P02GZa3LUD1uD-Payl41dWaW3oZSK7g.cache +1 -0
  85. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ID/IDb8KoiLtmLZLuTayZZRFbZN0JILZeJejeUyYRRGeAA.cache +0 -0
  86. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/IQ/IQoDS19BmJjvixXd16O_7P6DB-GRUEZgdNJexJ88fIc.cache +1 -0
  87. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/I_/I_zDBUxxL4b2Wk9_qqVs56Abw1jGccc4FgvKwuscswQ.cache +1 -0
  88. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ig/IgcuJMmmdeYrq2F3D721tC7ficyRm92HIrLkim5DCxQ.cache +1 -0
  89. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/J2/J2LffQpwOiS012wB_C4iABoBukTOT8hmHKFwpxPfYLQ.cache +1 -0
  90. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/JI/JITjXC3hXUPgOQhDYsVjhPNjtTISt0j5uz2bjfoiSHI.cache +1 -0
  91. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/KL/KL75rsyvMJSIkYkXRijxh8cs7V1wtfLPjuodISQK5vc.cache +0 -0
  92. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/KY/KYIakAXVeKvIhu5WQ8kwH9RU6xpV8HJfKrBqHy00VvE.cache +1 -0
  93. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Kw/KwqVMeMNxvnaSP-a-H5nkYyxloW_xoqR5JhEnqJ9puQ.cache +1 -0
  94. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/L1/L1KghIbeezpqVDyhAbCDc4pG11ElC5JpUl319-ZlZn8.cache +0 -0
  95. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lh/LhI7QMLwiVavmyvwYzdc_t_V9OATXaBO8aCB2swJFCk.cache +1 -0
  96. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lh/LhqYyoCtzXpfZq6UOhmZuZLSaAwZRX44sHfwPvPqezc.cache +2 -0
  97. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lo/Lovn2yBpV04WnAQwZeM3hLL015H5syYBH2ufgIc6qCM.cache +1 -0
  98. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lz/LznMZWa43whMHpqnPRsbUfREY3y_fiXQKaiKVEYW4fw.cache +0 -0
  99. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/MC/MC7GYdrSShtV64GB3hoINaYL3vCRZKq9KvwcwrJAdQo.cache +1 -0
  100. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/MU/MU6iF1YPAQqpVK_kVAtiJPtbHaYpYdOcO0g5bJ9exj8.cache +0 -0
  101. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Md/MdIg3XLcnbFsMXC-6xslVtmBvWH7Q21BSt9l5pm305o.cache +0 -0
  102. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Mw/Mwfi5Xeky61jhIuc6ooo4439CHOyz1hS48_taMRSlKM.cache +1 -0
  103. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ni/Ni5yuK9FFnhLe5HciROve12UIYstBdESWm0LfdcuVVs.cache +1 -0
  104. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Nz/Nz3hkLq4WlqgoHg_ChdHSXbP7fVmCWCTw0lH0jkMmDg.cache +0 -0
  105. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/O3/O38OvSNrhXKbxauuC8GOBBnKrt2-rPaDmfyrXScgHcA.cache +1 -0
  106. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/OS/OSm-zAlxXS63lBjvzJeSWfqq5d3D9fu-_nBVFWyQ4j0.cache +0 -0
  107. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Oa/Oazc9AJ4e_67dU0aArJeCNEeWJKMIFPtAJtxTJoUKcs.cache +1 -0
  108. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/P1/P1WYRlLMdpqE0KcFDUng5g9am4POfcOwowV2amR4tZ0.cache +1 -0
  109. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/PV/PVDpEMY_ha4kHETTb3QvjOBoBUP4PMjNDNcIAgmDy2I.cache +1 -0
  110. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Pl/PldDxSvU1o_UFPYTE0GJmUS9mHQXH88zEw5HN6GtlRE.cache +1 -0
  111. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Pu/PuU5S_LPnhAX43U1VVN3qP_sv0ph4stXSGo7I0e_jOw.cache +1 -0
  112. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/QJ/QJ6RPZNUkui_k3wTkb62zo8wczYY7q0B174GfSJjjWE.cache +2 -0
  113. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/QX/QXCyCL-Eeb3uHm9iOvs4anspZqeFbQnNyzDfIsXgzC8.cache +0 -0
  114. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/R1/R1F4Qf-kXTMH0fTLahalFTHtNBvgDfkOkrPyW8zeN_E.cache +0 -0
  115. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/R1/R1__Y-gz4zkDYrXWyCf6YTkvXO0RZlrpK6ynGGVuvnM.cache +0 -0
  116. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/R2/R2Xqb6eAeUW2xTaTaTjlkyUCirkb1qfYgW2CyY80VjM.cache +1 -0
  117. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/RM/RMXouh7GkRuhy8S6jnpxFD27HRVT0LEHj9iR53ps4o4.cache +1 -0
  118. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/RV/RVmt1mCn0tykR8xyBylvh-Hvi-Am87neA2IEkYHjg-g.cache +1 -0
  119. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Sb/Sb57Q81kn_46c151CSeuOFI2UarVIlevJHmB_glTpfI.cache +0 -0
  120. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Si/SiS4qKkPGbaIXzg2rpGa3SepickBkHi53MjRZreIVyw.cache +0 -0
  121. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/TF/TFylLOF6Be_hud-nZYcvvbD3NeyRKE8NUvv_JsuJ4cY.cache +0 -0
  122. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Tg/TgTXCuKAEg1DI5zjHO8tGMGuQGC9BRt9vgDZj2FdSa8.cache +1 -0
  123. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/UI/UIyRfqj_T27DnyWJiZK9BdUGTIDTQ9M953ArtrYz5fM.cache +1 -0
  124. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/U_/U_F-o3fo7oUYyn0O5KBlt3jOF53X_-4UuZb-_alPZPk.cache +1 -0
  125. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/U_/U_KCsVrX_QoGJ_FpUpCNU3XMT36CThwu8_0HYj_2k4w.cache +1 -0
  126. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/U_/U_ie5WwVJPItNZrqfbIrnZpaRokYT5klrYU92QSugd8.cache +0 -0
  127. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ub/Ub-oUCoAiliSW8ohVsmtsflc4nPeiBvcjzgNbPLYQRc.cache +0 -0
  128. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ud/UdvIJcVNQ_08Vaoyx4KuRGNjazpB9-qjOtDMTud8R0Y.cache +1 -0
  129. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Uz/UzEG5I_EszWbaSVnk497D0KfuIzsgHoPLVQd7e3mlQg.cache +1 -0
  130. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/V-/V-F9X0mrPgfTELxk9xdYnb27trOmB6nBDL973YWeOfU.cache +0 -0
  131. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/VA/VAOOXmbiiPy1jqpQQCDVrhkByG3pdeJoZCOvVkp-XVY.cache +1 -0
  132. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/VV/VVIuIm_HUOaEdZfXt-CmFQZb3ycoiXeeI-FV7nwkr0Y.cache +1 -0
  133. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/VW/VWjUCUH0gfcamZHDpILUcC_1PnGFykHGk0wh8NpIRbQ.cache +0 -0
  134. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/VX/VXHQHhwOUBuWlKPY6smpXG1xjASw927lyjUKBXBh3e0.cache +0 -0
  135. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Vn/VnE9ctuz42Ux3gd7YEwAa86NxA52PDCfU82OvtlrlX8.cache +1 -0
  136. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Vn/VnMqvZo9nqGF_5tt3gNbMyoG8jJVm0K0r1fANEBjfkw.cache +0 -0
  137. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/W1/W1YuEAoPMZTXfbxg_xWV9o2RP60SAKs5bhk7teKdL2g.cache +1 -0
  138. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/W2/W2ZyYMlYmyA7_1WcpiWhYUJa6wfPCZ5kZj_-Nuw31yM.cache +0 -0
  139. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Wg/WgwI9C5-mh_smtsTGVmH4y76T5ifM4M_hKL1fn-K8iw.cache +2 -0
  140. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ww/WwRKzl7ldAfUY6mvA4pcF6CJPsqgy9_yparRsi8cmpY.cache +0 -0
  141. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Wy/WyWAl1y93bbTZWLS767hNEj7IMJ8fUXatNCS-25hJXE.cache +1 -0
  142. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/X5/X5GHIj6tnz-w7d-60OaYcbzJczzkTBtm24BOxzoSDdo.cache +1 -0
  143. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/X6/X6jU4SPOD_b1ks9tCApsvWRa7q8cBYCjw3gI6Dwvr34.cache +2 -0
  144. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/X8/X88lT-cwuuj8gqiNY83uVqXFgeLcaHMc9Xh2X4Iux6k.cache +0 -0
  145. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/XQ/XQ0aFc1cceisG4P8qUPhW8z1H3I71pMguVRRMgJ66cs.cache +5 -0
  146. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Xh/XhXLVYOEEwpzOBAWDdiCEpTMz7vC8wnlBHYHJkySh-0.cache +1 -0
  147. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/YB/YBJNyX7HNPq78obeHYRGnJKSVl9EtRPbcGD253-ia34.cache +0 -0
  148. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Yu/YupDX89OAJ6u3BHBW-UJgO3nDfi7hwlpf_JHlnM8b6k.cache +1 -0
  149. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ZH/ZHN5sHdNMxUCl3Ese5T5_AzQbD9WHqpgBL4PBOrgXJY.cache +1 -0
  150. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ZP/ZPRvYWthjzuQ0tqk5AdgQbeTUqhDboF8bvTtdrmg4Jo.cache +1 -0
  151. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ZV/ZVu2Ed9wpdsPLKStP971oLEJBwgJQHLInXIiQkIWC04.cache +0 -0
  152. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Zb/ZbnyIl6znMAVquD2ZD5OYA9SPXmQJYWU7V8F2Hgp3Uc.cache +0 -0
  153. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Zj/ZjALwFkjfG3uebsyy_CeJp5VQMJLE03zxPxkNp-sZDA.cache +0 -0
  154. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/_E/_E-Bix511H4RJnJUAkPWvnNw4IThIvS9CEAku1gsVcg.cache +0 -0
  155. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/_F/_Fu404i1O4mKpjPluBsq-3FZQnyQvla_6jDnH03Lpw8.cache +2 -0
  156. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/a-/a-t90hz_PZnc6ImKhk-cIh_WBB9vi_rChKzLv4hMBqw.cache +1 -0
  157. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/a5/a5cnzGcRAu4dPakq4_DHH9GanK42Ov5O1F62oeJR4Zo.cache +1 -0
  158. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/a5/a5uFYzSt5Xm8ZjP5N42LcV7y94YTaEkIep8jBUeErBc.cache +1 -0
  159. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aJ/aJK2kxoM9CsnZpxiFvP6RoP0sxHBiix9X1P6Mhy9Dcg.cache +2 -0
  160. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aO/aOU10S2QEOBHcdKwGRfXqqHdYshmYD20LYiJIGMzIa0.cache +1 -0
  161. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aZ/aZEdK7dgijyjIs26V_QbKsDgO5JxeYXiT0Sl28M0e-U.cache +0 -0
  162. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aq/aqBnFJWuQ-xmdUL8_asWtElNRrMr0W60LVdDqpt43L8.cache +1 -0
  163. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aq/aqNor7ePvH9sS4jPTBqDuXgPIzCEYDmzv6OL8nFaBfc.cache +2 -0
  164. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/b5/B5yawfIgrEUdQrBwKkk65ra3p7vzQakH5rHh61IUCGQ.cache +0 -0
  165. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/b5/b5KTv2Hrf5faN7X4XahT1s8L5t-EANtcFKrMEsGm3lw.cache +1 -0
  166. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bF/bFemYCjG73k2_Ys77S7qNyW7CYcyw4bngyc0OGneI-s.cache +1 -0
  167. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bG/bGdy8gJL8acOmxK8AbkYbxNuakf4LlMZ-zPBkyL0E-0.cache +1 -0
  168. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bK/bKm8sxC3i0ycUMXr6pnD61MdwytUWfpNOJlBY6qJaWg.cache +1 -0
  169. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/dA/dA1M22RMQvVwb74tbFg-_237SferZuCI10s4R0zx8NI.cache +0 -0
  170. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/dF/dFOzXjFeRtB5bukRI9wGrh2O_GkOeBPnrJRMiv8_ZbM.cache +0 -0
  171. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/dw/dwbXKkD4yllXOeD4T7BKoGvLS26j9lxMkjMiIxfyt6E.cache +0 -0
  172. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/eO/eOhX0bq10_h3P-ISuztuJ9tqU9WI-YU21LY8uIKWjCI.cache +0 -0
  173. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/eT/eTgN8O1TgsFV61pclFzCmmJ9qT7MgyGvtQrmRtJoNeg.cache +0 -0
  174. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ec/ec5x3WtYVdBZAlGgRklnM5CWLyA6JeDBJT_1HOhXF4g.cache +1 -0
  175. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/eu/eu6Xg0psMCuHIWG0WjCo9wwNOlWs-Z5OH4SyGEmdTNQ.cache +1 -0
  176. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/fC/fC-TBNdh4rVupPn2ObyZeIx6OSlpBSBQZfIzywI6xx0.cache +0 -0
  177. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/fC/fCGqdV7zjLjwzE_j81Q26V2av1OhelK9ekz-obYezyM.cache +1 -0
  178. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/fR/fRIbNtGTaNqdwIDyusrUmllglSGMNnqnw7VOLvf5D_k.cache +1 -0
  179. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/fq/fq7SFxQSEFZCuS7jQj0n-BQfbJ5mpLpmJQsd9mJVq68.cache +1 -0
  180. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gG/gGBN3yxvq8azMjDv3hsSw_zLUj9KLuqHPDXZK8x8pFc.cache +0 -0
  181. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gQ/gQzw0n2XxT1vPdv-JNlsvC4baxnQXS_my3g0GHgk2DM.cache +0 -0
  182. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gc/gcwevUTNs8bX7r0PgMxjPfBObyrl1oUiYzRUtDwso20.cache +1 -0
  183. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gd/gd3J0EmNeiTh2GzxcAKItmtUnUay9NG4Sm2vkiLKvmA.cache +1 -0
  184. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gj/gjXteWe57D8FaBOQUw29N_mwHCeTQW8oLjyv8fu3wNw.cache +3 -0
  185. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gt/gtFeEhjHn0G9WhgiMKaNtXVgNYW9s_wBLE0VGegeAN8.cache +1 -0
  186. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/hA/hA4-M5cp310ZkSe59_BWszdgXy7mmYagSRCfelGBA9o.cache +1 -0
  187. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/hc/hcXm7DBIrn3OjXXbh6UkevkxWDcflOZ9csWRVYgjSac.cache +0 -0
  188. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/hj/hje-P0mJOOD6UQ7CsJ7BNZBSdKcCkvwHijuCCtQDWMw.cache +1 -0
  189. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/iC/iC3FCadetljjEIeMWfeqqDoMxhJi6rI20BpiVxtvgS4.cache +1 -0
  190. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/iV/iV16_jyEayI_vLgHw3HFhtJAiVOCIlzFho0Yt7a4v_Y.cache +0 -0
  191. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/j6/j62KRIr4T81zq1Ujpg7AJRQdI0ry9HGKPt4nK6fRt1g.cache +1 -0
  192. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/jR/jRg0Zbr59-UMtrWO5t2VWNI3GqU7XWOUsE44dX5cPyk.cache +0 -0
  193. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/jj/jj9HUpCSrLEyONEZNLLkgJ8hJmxOCLpcVJeiBa0KDsE.cache +1 -0
  194. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/jq/jqnMk9arxuef2cdSQuxj3WOQuAfGKup3H2pjO7x1DOg.cache +0 -0
  195. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/k1/k14rvggyKI9dk-yVjn-Lk0p8qU360H_JuVG9aZ4q0OM.cache +1 -0
  196. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/kb/Kb8Z49kajAX1vyy5d4-gA8StHhQp5yOUs0wtdZ7m8Hc.cache +1 -0
  197. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/kb/kbEMkrgp2k0pezn_gFfMqA142QwoJYBKMj7cEkE-Hag.cache +1 -0
  198. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/lD/lDpZHp5gBhRdNHdj1TwWq1_LZ_a56lxeksxqaEs2efA.cache +1 -0
  199. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/lL/lLUIzpNuP0NYh0_joJRWkVJ0OF9W3CyzdFBfs3818Lc.cache +1 -0
  200. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mE/mEfGHxLvdPQrcbpjLw4q_wOPirMzrR4z58KgozQ1zNY.cache +1 -0
  201. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mM/mMZ3DR5b7kx70JtEg-ImWOa_V1jnHcWgHqNqapxIMXk.cache +0 -0
  202. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mX/mXCT6vriuTtwLaKGnTa5hwXSrwGtAmP6pV5lmjbHaYM.cache +0 -0
  203. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mZ/mZjIy4zRS4hbS4vWHpdKd7jeZgLatEx_nlFqv_KSCrs.cache +0 -0
  204. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mg/mge36-9r2gGuKcPoghbLDM72AV4gIVTl6gQDbk7hrkg.cache +1 -0
  205. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/nK/nKZaLuUqTl9pf5Nb1oVuabxd74q4oN8YTBeo6bNd-Vk.cache +0 -0
  206. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/nP/nPbHGaYfJSLZ2K3YTROe7T1RPqKoBQJwawQtZ_FN1-I.cache +0 -0
  207. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/o9/o9KyTznHG0ZIHDI7kTg1Jp78qaga7gJqouXSKdocEjA.cache +1 -0
  208. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/oB/oBupyQ9cW436mBji6Rp7TtHE6CX_r8iq2sCBo0LNbc8.cache +1 -0
  209. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/oN/oN3TypgxDDLqcxy0Funa4RVCYXS-7qn6D56wgBiUT2Q.cache +1 -0
  210. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/oW/oWo9dphQsanmdoiEL4YOq-nygJy3mBHxuB-V0YKtqKg.cache +0 -0
  211. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/om/omGcA_eTFAFIH3RJaPOpEW3yz0074cob3hozQFLOAxk.cache +1 -0
  212. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ot/otpWM-gZogHCGUHAd2Xu_B_U36zeJ9dAR2xKLiDheVE.cache +1 -0
  213. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/p0/p0WHrZZBaXbPaNj5XmQGTli4mi08Rv8DidQfwj28a6w.cache +0 -0
  214. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/p5/p5Qqrs_bvLEarcHNwiFMoZXaTWvShlq8KdaiIXvi7g4.cache +1 -0
  215. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pA/pAvUFBt71eJx7E7oQbIxrEZ8YcMo9kboyGxjk73ZWrI.cache +1 -0
  216. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pB/pBwzUQUu-GcmLiQwn6KnbbDP0ipnVHzVaeArqdpqi98.cache +0 -0
  217. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pC/pCePfKbmTQ6s2Tl7ki3oBput2ruhpCzpa6Vvejbb5xg.cache +1 -0
  218. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pS/pSLY6X9P48cnC-drvpZwa1ubJu-hjpiaTx_7Bj45riY.cache +1 -0
  219. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/q6/q6BYa32YJF11eGVapO4ouNl6gayPIsARgMavlzZmoi0.cache +0 -0
  220. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qW/Qwu_HFjM_p33h0ukEd8eZtvuDh1Zw5x1w77CDlTopH8.cache +1 -0
  221. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qW/qWlVTm6ozTv1T_Rvda-EsADQdVTcmfAesyZAq5Y4Ht4.cache +1 -0
  222. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qY/QYP6D7Cl8GTs3LFfMQg5vYyDceeOpPLwxvPpYiKHzIU.cache +0 -0
  223. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qY/qY78GTTnufmP1eP2CE16x833zGfQ0F5EVCFtUTMQ7Mw.cache +1 -0
  224. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qY/qy4PIHHAIEUKVx3kHjiN5YyIrun3jtvdSX5yXMkB2PQ.cache +0 -0
  225. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qm/qmZZzCnL9PLIyZ0iBu6Alr69AUfHHI1fKdNRRgG04yg.cache +1 -0
  226. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/rP/rPrNeVrYtj3sM9uesyX26XheSoRwAHJAmshFxNu9Bjg.cache +1 -0
  227. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/rP/rp52ANh-KNLY9IZY1lxAbAsbbtpE0S41_F9fq3W6bq4.cache +0 -0
  228. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/s4/s4tbhiIn_CLebHU0ldR1hjB8M4TebDv0UHjWrn41K1c.cache +0 -0
  229. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/s5/s5yv3jYvjyKZJ8SMzpj94eMKEuX46lAWV1ApHF-6bsM.cache +1 -0
  230. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/sO/sOBPF_p4Te56V9vdLV0Ywn6djNbmdPSIzvgYNPnAXYc.cache +0 -0
  231. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/sv/sv0a_JAC4GSc_cK-2OUAzhFwm_K3qzSfDefwpcqOCk4.cache +1 -0
  232. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/sv/svHBVuxn5XQE6HEBJ4AWbdxsIDZHr5qjwrGP-UVLxk4.cache +1 -0
  233. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/sw/sw2EAksRkslJNoJJCTS2FPOfHWCYvsS86AxmRMPjens.cache +1 -0
  234. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/t1/t1cv6bP9cTAIs82lyIsnXGeAwB1KNVY5_5rgUvelr04.cache +0 -0
  235. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/tO/To1SPyNegqysLIqhSzrNQPh1VKKj19MespjJediCde4.cache +1 -0
  236. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/tO/tOPkZNrO9FRDhSlCf7VWOexxRq2CE2X4_6KjyxJkq2A.cache +0 -0
  237. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/tR/tRoxwnX8bACHK5pW9tIi4ILY4XuYTIpueH0fGr2t0rc.cache +1 -0
  238. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/t_/t_bP70PmOB70862dwKmCTkmZuzTqCreOzNYW4Yn2n6A.cache +1 -0
  239. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/t_/t_ltg5_gjc0TqJfse-jdOUGwQu5AiK0znzxmaWt05x8.cache +0 -0
  240. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/uj/ujdE_ewC5UIxr6uw5F7YRfKKWiu8-15wzBlOjYHsnkQ.cache +1 -0
  241. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ut/ut8uBMdgxX8_wfU0l6kGew6H8TLXAj74kFnaI252F3k.cache +1 -0
  242. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ut/utQEOZtBKQK_bUUDeZX4Mgk00L4AOMVyq6zrKAoo1Xw.cache +0 -0
  243. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/v4/V4ZL0hYAfHe81zfd7otsIeeWkSiHQ26MT8zObK74mSA.cache +1 -0
  244. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/v4/v4pe2JlWkzR-IW0F4Bhw4WEAwHNgeT9Df5rOmKYSwAI.cache +1 -0
  245. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/vm/vmjBl9ZCF5hj4sG4e2nid94GcRQYmsOsu-_Q3Zlud5c.cache +0 -0
  246. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/vz/vzBoVc4GQWi4UFp-4dBJnzrhyUuokPV8SCOxsdpOht8.cache +2 -0
  247. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/wM/wMWxmf8BN_NAJRCyardukpfDMwts44Bz2a8doi-49Rg.cache +1 -0
  248. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/x7/x7KkTV3ibfIEysLB_ug5bfmnn2VLV_BldukPR3EoPBk.cache +0 -0
  249. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/x7/x7iSOdqAIVmVpn9ujTwJ_C7EqUgmMSri5vjjHdRIX10.cache +1 -0
  250. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/xY/xYdD9O1JRIfpVj9Kw_b3JTUBQZLI_dcy-bf9uXEp-jg.cache +0 -0
  251. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/xx/xxkulLgT-tkVeDC50gUXRGGMou47BUdlYOwgs0j5muY.cache +1 -0
  252. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/yn/yn_3aZZwyjcI0O6fwisZ7zvcu4Gq5bV31g3tHFxfQNg.cache +1 -0
  253. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/yq/yqwjyepbYY4ctoMOySWiOIWUYwzl_BczAmXqJ5DPvb0.cache +0 -0
  254. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/z9/z9HQmzff5j_6CFyk6eQ52nYt9cPLXsxDQY0Yep1Hz-0.cache +1 -0
  255. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/zM/zMvcc87IG1SRbqwUNtWQfHgeWr5XN36OU8vg-v3rUus.cache +0 -0
  256. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/zn/znjQpjNzh1iUAe9DljeFghnStRvqNIr1GuOTibVcEJQ.cache +0 -0
  257. data/test/dummy/tmp/testrep/BaaRamEwe.txt +5 -0
  258. data/test/dummy/tmp/testrep/BarFoo.txt +5 -0
  259. data/test/dummy/tmp/testrep/BazQuux.txt +5 -0
  260. data/test/dummy/tmp/testrep/FooBar.txt +5 -0
  261. data/test/dummy/tmp/testrep/NewEncryptedPage.txt +5 -0
  262. data/test/dummy/tmp/testrep/NewPage.txt +5 -0
  263. data/test/dummy/tmp/testrep/users/testy.json +1 -0
  264. data/test/dummy/tmp/wikirep/FrontPage.txt +5 -0
  265. data/test/dummy/tmp/wikirep/users/chrismo.json +1 -0
  266. data/test/dummy/wikirep/EncryptedPage.txt +0 -0
  267. data/test/dummy/wikirep/FrontPage.txt +11 -4
  268. data/test/dummy/wikirep/users/chrismo.json +1 -0
  269. data/test/helpers/wiki_helper_test.rb +2 -0
  270. data/test/lib/clwiki/clwiki_test_helper.rb +19 -2
  271. data/test/lib/clwiki/file_owner_test.rb +58 -0
  272. data/test/lib/clwiki/file_test.rb +91 -56
  273. data/test/lib/clwiki/memory_index_test.rb +61 -0
  274. data/test/lib/clwiki/page_test.rb +72 -148
  275. data/test/lib/clwiki/test_base.rb +19 -19
  276. data/test/test_helper.rb +7 -5
  277. metadata +498 -23
  278. data/lib/cl_wiki/find_in_file.rb +0 -33
  279. data/lib/cl_wiki/index.rb +0 -458
  280. data/lib/cl_wiki/tools/cron.reminders.rb +0 -241
  281. data/lib/cl_wiki/tools/movepages.rb +0 -27
  282. data/lib/cl_wiki/tools/pagestomove.txt +0 -56
  283. data/lib/cl_wiki/tools/rublog/clWiki.rb +0 -62
  284. data/lib/cl_wiki/tools/rublog/readme.txt +0 -2
  285. data/lib/cl_wiki/tools/singlepage.rb +0 -58
  286. data/lib/cl_wiki/tools/test/singlepagetest.rb +0 -9
  287. data/lib/cl_wiki/tools/thunderbird.rb +0 -23
  288. data/test/lib/clwiki/find_in_file_test.rb +0 -111
  289. data/test/lib/clwiki/index_test.rb +0 -32
@@ -2,25 +2,6 @@ production:
2
2
  # path to the root directory that stores the page files
3
3
  wiki_path: wikirep
4
4
 
5
- # useIndex can be one of the three numbers:
6
- # 0 No Index
7
- # 1 DRb Index Server
8
- # 2 Local Index Server
9
-
10
- useIndex: 0
11
-
12
- # useIndexForPageExists determines if the index is referenced for
13
- # determining if a page exists rather than querying the file system. In
14
- # some cases, the file system (due to OS caching and whatnot) outperforms
15
- # the index. This option is ignored if useIndex is set to No Index.
16
-
17
- useIndexForPageExists: false
18
-
19
- # the port the DRb Index Server uses. This setting is irrelevant if
20
- # useIndex is anything other than 1
21
-
22
- # indexPort: 9111
23
-
24
5
  # set this to false for a read-only wiki. Useful with Blogki
25
6
 
26
7
  editable: false
@@ -34,18 +15,13 @@ production:
34
15
  # BETA option -- probably not even a sample.template.htm included in the
35
16
  # distribution)
36
17
 
37
- # template mytemplate.htm
18
+ # template: mytemplate.htm
38
19
 
39
20
  # If you want to restrict the Recent view to only published pages, you
40
21
  # can configure a custom tag here. If this isn't defined, then every
41
22
  # page will appear on the Recent view.
42
23
  #
43
- # publishTag <publish>
44
-
45
- # showSourceLink can be turned on to add a page link in the footer that
46
- # is a file:// url direct to the raw page. Default is false.
47
- #
48
- # showSourceLink true
24
+ # publishTag: <publish>
49
25
 
50
26
  # time format for display of last page update
51
27
  #
@@ -55,10 +31,22 @@ production:
55
31
  #
56
32
  custom_formatter_load_path: []
57
33
 
34
+ # Require a user account to access the wiki. Defaults to false.
35
+ #
36
+ # use_authentication: false
37
+
38
+ # Default setting for encryption option on edit page. Only used if
39
+ # use_authentication is true.
40
+ #
41
+ # encryption_default: false
42
+
43
+ # The owning user account for the wiki. Must be set if
44
+ # use_authentication is true.
45
+ #
46
+ # owner: username
47
+
58
48
  test:
59
49
  wiki_path: tmp/testrep
60
- useIndex: 0
61
- useIndexForPageExists: false
62
50
  editable: true
63
51
  page_update_format: '%B %d, %Y'
64
52
  custom_formatter_load_path: []
@@ -66,8 +54,6 @@ test:
66
54
  development:
67
55
  # path to the root directory that stores the page files
68
56
  wiki_path: wikirep
69
- useIndex: 0
70
- useIndexForPageExists: false
71
57
  editable: true
72
58
  page_update_format: '%B %d, %Y'
73
59
  custom_formatter_load_path: []
@@ -1,8 +1,9 @@
1
- require 'cl_wiki/configuration'
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency 'cl_wiki/configuration'
2
4
 
3
5
  filename = File.join(File.dirname(__FILE__), '..', '..', 'config', 'clwiki.yml')
4
6
 
5
- conf_hash = YAML::load(::File.open(filename))[Rails.env]
7
+ conf_hash = YAML.safe_load(::File.open(filename))[Rails.env]
6
8
  conf_hash['wiki_path'] = ::File.expand_path(conf_hash['wiki_path'], Rails.root)
7
9
  $wiki_conf = ClWiki::Configuration.new(conf_hash)
8
- $wiki_path = $wiki_conf.wiki_path
@@ -1,14 +1,23 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ClWiki::Engine.routes.draw do
2
4
  root to: 'page#show'
3
5
 
4
6
  # legacy CGI
5
7
  match '/clwikicgi.rb', to: 'page#show', via: [:get], as: 'legacy'
6
8
 
9
+ # Ordering of routes matters! Anything specific, like `find` needs to be
10
+ # _before_ the `/:page_name` route, otherwise it matches on `/:page_name`
11
+ # before matching on the specific route.
12
+
7
13
  get '/find' => 'page#find', as: 'page_find'
8
14
  post '/find' => 'page#find'
9
15
 
10
16
  get '/recent' => 'page#recent', as: 'recent'
11
17
 
18
+ get '/login', to: 'sessions#new'
19
+ post '/login', to: 'sessions#create'
20
+
12
21
  get '/:page_name' => 'page#show', as: 'page_show'
13
22
  get '/:page_name/edit' => 'page#edit', as: 'page_edit'
14
23
  post '/:page_name' => 'page#update'
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'cl_wiki/engine'
2
4
 
5
+ require_relative 'cl_wiki_lib'
6
+
3
7
  module ClWiki
4
8
  =begin
5
9
  http://edgeguides.rubyonrails.org/engines.html#inside-an-engine
@@ -9,4 +13,4 @@ module ClWiki
9
13
  options, the file where your engine's module is defined is perfect for that. Place
10
14
  the methods inside the module and you'll be good to go.
11
15
  =end
12
- end
16
+ end
@@ -1,83 +1,43 @@
1
- require File.dirname(__FILE__) + '/index'
1
+ # frozen_string_literal: true
2
+
2
3
  require 'yaml'
3
4
 
4
5
  $defaultConfFile = 'clwiki.yml'
5
6
 
6
7
  module ClWiki
8
+ # noinspection RubyTooManyInstanceVariablesInspection
7
9
  class Configuration
10
+ attr_accessor :wiki_path, :cssHref, :template, :publishTag, :url_prefix,
11
+ :global_edits, :page_update_format, :use_authentication,
12
+ :owner, :encryption_default
13
+ attr_reader :custom_formatter_load_path, :edit_rows, :edit_cols, :editable
8
14
 
9
- USE_INDEX_NO = 0
10
- USE_INDEX_DRB = 1
11
- USE_INDEX_LOCAL = 2
12
-
13
- attr_accessor :wiki_path, :cgifn, :indexPort, :cssHref, :template, :useGmt,
14
- :publishTag, :url_prefix, :global_edits, :cgifn_from_rss, :stats_name,
15
- :index_log_fn, :page_update_format
16
- attr_reader :custom_formatter_load_path
17
-
18
- def wait_on_threads
19
- # Ruby kills any threads as soon as the main process is done. Any
20
- # threads created should be registered here. The last
21
- # line of the CGI script should call out to wait_on_threads to make
22
- # sure nothing running async in the background is terminated too early
23
- @threads.each do |thread|
24
- thread.join
25
- end if !@threads.nil?
26
- end
27
-
28
- def wait_on_thread(thread)
29
- @threads = [] if !@threads
30
- @threads << thread
31
- end
32
-
33
- def useIndex
34
- @useIndex
35
- end
36
-
37
- def useIndex=(value)
38
- @useIndex = value.to_i
15
+ def initialize(hash = {})
16
+ default_hash.merge(hash).each do |k, v|
17
+ instance_variable_set(:"@#{k}", v)
18
+ end
39
19
  end
40
20
 
41
- def edit_rows
42
- @edit_rows
21
+ def default_hash
22
+ {
23
+ url_prefix: '/',
24
+ publishTag: nil,
25
+ useIndexForPageExists: false,
26
+ edit_rows: 25,
27
+ edit_cols: 80,
28
+ custom_formatter_load_path: [],
29
+ use_authentication: false
30
+ }
43
31
  end
44
32
 
45
33
  def edit_rows=(value)
46
34
  @edit_rows = value.to_i
47
35
  end
48
36
 
49
- def edit_cols
50
- @edit_cols
51
- end
52
-
53
37
  def edit_cols=(value)
54
38
  @edit_cols = value.to_i
55
39
  end
56
40
 
57
- def useIndexForPageExists
58
- @useIndexForPageExists
59
- end
60
-
61
- def useIndexForPageExists=(value)
62
- if value.class == String
63
- @useIndexForPageExists = (value =~ /true/i)
64
- else
65
- @useIndexForPageExists = value
66
- end
67
- end
68
-
69
- def access_log_index
70
- @access_log_index
71
- end
72
-
73
- def access_log_index=(value)
74
- if value.class == String
75
- @access_log_index = (value =~ /true/i)
76
- else
77
- @access_log_index = value
78
- end
79
- end
80
-
81
41
  def override_access_log_index
82
42
  @orig_access_log_index_value = @access_log_index
83
43
  @access_log_index = false
@@ -87,85 +47,16 @@ module ClWiki
87
47
  @access_log_index = @orig_access_log_index_value if @orig_access_log_index_value
88
48
  end
89
49
 
90
- def editable
91
- @editable
92
- end
93
-
94
50
  def editable=(value)
95
- if value.class == String
96
- @editable = (value =~ /true/i)
97
- else
98
- @editable = value
99
- end
100
- end
101
-
102
- def showSourceLink
103
- @showSourceLink
104
- end
105
-
106
- def showSourceLink=(value)
107
- if value.class == String
108
- @showSourceLink = (value =~ /true/i)
109
- else
110
- @showSourceLink = value
111
- end
51
+ @editable = if value.class == String
52
+ (value =~ /true/i)
53
+ else
54
+ value
55
+ end
112
56
  end
113
57
 
114
- def self.load(filename=$defaultConfFile)
115
- $wiki_conf = self.new(YAML::load(::File.open(filename)))
116
- $wiki_path = $wiki_conf.wiki_path
117
- $wiki_conf
58
+ def self.load(filename = $defaultConfFile)
59
+ $wiki_conf = self.new(YAML.safe_load(::File.open(filename)))
118
60
  end
119
-
120
- def initialize(hash={})
121
- default_hash.merge(hash).each do |k, v|
122
- instance_variable_set(:"@#{k.to_s}", v)
123
- end
124
- end
125
-
126
- def default_hash
127
- {
128
- :url_prefix => '/',
129
- :indexPort => ClWiki::Indexer.defaultPort,
130
- :cgifn => 'clwikicgi.rb',
131
- :default_recent_changes_name => "Recent Changes",
132
- :recent_changes_name => "Recent Changes",
133
- :stats_name => "Hit Counts",
134
- :useGmt => false,
135
- :publishTag => nil,
136
- :useIndexForPageExists => false,
137
- :showSourceLink => false,
138
- :cgifn_from_rss => 'blogki.rb',
139
- :edit_rows => 25,
140
- :edit_cols => 80,
141
- :access_log_index => false,
142
- :index_log_fn => nil,
143
- :custom_formatter_load_path => []
144
- }
145
- end
146
-
147
- def default_recent_changes_name=(value)
148
- if @recent_changes_name == @default_recent_changes_name
149
- @recent_changes_name = value
150
- end
151
- @default_recent_changes_name = default_recent_changes_name
152
- end
153
-
154
- def default_recent_changes_name
155
- @default_recent_changes_name
156
- end
157
-
158
- def recentChangesName=(value)
159
- @recent_changes_name = value
160
- @recent_changes_name = @default_recent_changes_name if @recent_changes_name.empty?
161
- end
162
-
163
- alias recent_changes_name= recentChangesName=
164
-
165
- def recentChangesName
166
- @recent_changes_name
167
- end
168
-
169
- alias recent_changes_name recentChangesName
170
61
  end
171
62
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ClWiki
2
4
  class Engine < ::Rails::Engine
3
5
  isolate_namespace ClWiki
4
6
 
5
7
  initializer 'cl_wiki.assets.precompile' do |app|
6
- app.config.assets.precompile += %w(application.css application.js)
8
+ app.config.assets.precompile += %w[application.css application.js]
7
9
  end
8
10
  end
9
11
  end
@@ -1,168 +1,191 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fileutils'
2
4
  require 'time'
3
5
 
4
- require_relative 'page'
5
-
6
- $wikiPageExt = '.txt'
7
-
8
6
  module ClWiki
7
+ FILE_EXT = '.txt'
8
+
9
9
  class File
10
- attr_reader :name, :fileExt, :wikiRootPath, :pagePath, :modTimeAtLastRead, :metadata
11
- attr_accessor :clientLastReadModTime
12
-
13
- def initialize(fullPageName, wikiRootPath, fileExt=$wikiPageExt, autocreate=true)
14
- # fullPageName must start with / ?
15
- @wikiRootPath = wikiRootPath
16
- fullPageName = ClWiki::Util.convertToNativePath(fullPageName)
17
- fullPageName.ensure_slash_prefix
18
- @pagePath, @name = ::File.split(fullPageName)
19
- @pagePath = '/' if @pagePath == '.'
20
- @fileExt = fileExt
21
- @metadata = {}
22
- @metadata_keys = ['mtime']
23
- if autocreate
24
- if file_exists?
25
- readFile
26
- else
27
- writeToFile(default_content, false)
28
- end
10
+ attr_reader :name, :mod_time_at_last_read, :metadata, :owner
11
+ attr_accessor :client_last_read_mod_time
12
+
13
+ def initialize(page_name, wiki_root_path, auto_create: true, owner: PublicUser.new)
14
+ @wiki_root_path = wiki_root_path
15
+ @owner = owner
16
+ @name = ::File.basename(ClWiki::Util.convert_to_native_path(page_name))
17
+ @metadata = Metadata.new
18
+ if auto_create
19
+ file_exists? ? read_file : write_to_file(default_content, false)
29
20
  end
30
21
  end
31
22
 
32
- def content_is_default?
23
+ def has_default_content?
33
24
  @contents.to_s == default_content
34
25
  end
35
26
 
36
- def delete
37
- File.delete(fullPathAndName) if File.exists?(fullPathAndName)
27
+ def default_content
28
+ "Describe #{@name} here."
38
29
  end
39
30
 
40
- def default_content
41
- "Describe " + @name + " here."
31
+ def delete
32
+ ::File.delete(full_path_and_name) if file_exists?
42
33
  end
43
34
 
44
35
  def file_exists?
45
- FileTest.exist?(fullPathAndName)
36
+ FileTest.exist?(full_path_and_name)
46
37
  end
47
38
 
48
- def fullPath
49
- res = ::File.expand_path(::File.join(@wikiRootPath, @pagePath))
50
- raise 'no dirs in fullPath' if res.split('/').empty?
51
- res
39
+ def full_path_and_name
40
+ ::File.expand_path(@name + FILE_EXT, @wiki_root_path)
52
41
  end
53
42
 
54
- def fullPathAndName
55
- ::File.expand_path(@name + @fileExt, fullPath)
43
+ def content
44
+ @contents
56
45
  end
57
46
 
58
- def fileName
59
- raise Exception, 'ClWikiFile.fileName is deprecated, use fullPathAndName'
60
- # fullPathAndName
47
+ def content=(new_content)
48
+ write_to_file(new_content)
61
49
  end
62
50
 
63
- def content
64
- @contents
51
+ def write_to_file(content, check_mod_time = true)
52
+ do_mod_time_check if check_mod_time
53
+
54
+ update_metadata
55
+ file_contents = String.new.tap do |s|
56
+ s << @metadata.to_s
57
+ s << (content_encrypted? ? @owner.lockbox.encrypt(content) : content)
58
+ end
59
+ ::File.binwrite(full_path_and_name, file_contents)
60
+ ::File.utime(@metadata['mtime'], @metadata['mtime'], full_path_and_name)
61
+ read_file
65
62
  end
66
63
 
67
- def content=(newContent)
68
- writeToFile(newContent)
64
+ def read_file
65
+ @mod_time_at_last_read = ::File.mtime(full_path_and_name)
66
+
67
+ raw_bytes = ::File.binread(full_path_and_name)
68
+ @metadata, raw_content = Metadata.split_file_contents(raw_bytes)
69
+
70
+ apply_metadata
71
+
72
+ @contents = if content_encrypted?
73
+ @owner.lockbox.decrypt_str(raw_content)
74
+ else
75
+ raw_content.force_encoding('UTF-8')
76
+ end
69
77
  end
70
78
 
71
- def writeToFile(content, checkModTime=true)
72
- if checkModTime
73
- # refactor, bring raiseIfMTimeNotEqual back into this class
74
- ClWiki::Util.raiseIfMTimeNotEqual(@modTimeAtLastRead, fullPathAndName)
75
- unless @clientLastReadModTime.nil?
76
- ClWiki::Util.raiseIfMTimeNotEqual(@clientLastReadModTime, fullPathAndName)
77
- end
78
- end
79
+ def read_metadata(lines)
80
+ @metadata = Metadata.new(lines)
81
+ end
79
82
 
80
- make_dirs(fullPath)
81
- ding_mtime
82
- ::File.open(fullPathAndName, 'w+') do |f|
83
- f.print(metadata_to_write)
84
- f.print(content)
85
- end
86
- ::File.utime(@metadata['mtime'], @metadata['mtime'], fullPathAndName)
87
- readFile
83
+ def apply_metadata
84
+ @mod_time_at_last_read = Time.parse(@metadata['mtime']) if @metadata.has? 'mtime'
85
+ ensure_same_owner!
88
86
  end
89
87
 
90
- def ding_mtime
91
- @metadata['mtime'] = Time.now
88
+ def content_encrypted?
89
+ @metadata['encrypted'] == 'true'
92
90
  end
93
91
 
94
- def metadata_to_write
95
- @metadata.collect { |k, v| "#{k}: #{v}" }.join("\n") + "\n\n\n"
92
+ def encrypt_content!
93
+ raise "Owner <#{@owner.name}> cannot encrypt" unless @owner.can_encrypt?
94
+
95
+ @metadata['encrypted'] = 'true'
96
96
  end
97
97
 
98
- def make_dirs(dir)
99
- # need to commit each dir as we make it, which is why we just don't
100
- # call File::makedirs. Core code copied from ftools.rb
101
- parent = ::File.dirname(dir)
102
- return if parent == dir or FileTest.directory? dir
103
- make_dirs parent unless FileTest.directory? parent
104
- if ::File.basename(dir) != ""
105
- Dir.mkdir dir, 0755
106
- end
98
+ def do_not_encrypt_content!
99
+ @metadata['encrypted'] = 'false'
107
100
  end
108
101
 
109
- def readFile
110
- ::File.open(fullPathAndName, 'r') do |f|
111
- @modTimeAtLastRead = f.mtime
112
- raw_lines = f.readlines
113
- metadata_lines, content = split_metadata(raw_lines)
114
- read_metadata(metadata_lines)
115
- apply_metadata
116
- @contents = content
102
+ private
103
+
104
+ def do_mod_time_check
105
+ ClWiki::Util.raise_if_mtime_not_equal(@mod_time_at_last_read, full_path_and_name)
106
+ unless @client_last_read_mod_time.nil?
107
+ ClWiki::Util.raise_if_mtime_not_equal(@client_last_read_mod_time, full_path_and_name)
117
108
  end
118
109
  end
119
110
 
120
- def split_metadata(raw_lines)
121
- start_index = 0
122
- raw_lines.each_with_index do |ln, index|
123
- if ln.chomp.empty?
124
- next_line = raw_lines[index+1]
125
- if next_line.nil? || next_line.chomp.empty?
126
- if all_lines_are_metadata_lines(raw_lines[0..index-1])
127
- start_index = index + 2
128
- end
129
- break
130
- end
131
- end
111
+ def update_metadata
112
+ @metadata['mtime'] = Time.now
113
+ @metadata['owner'] = @owner.name
114
+ end
115
+
116
+ def ensure_same_owner!
117
+ meta_owner = @metadata['owner']
118
+ is_legacy_file = meta_owner.to_s.empty?
119
+ unless is_legacy_file || meta_owner == @owner.name
120
+ raise "Owner must match: <#{meta_owner}> - <#{@owner.name}>"
132
121
  end
122
+ end
123
+ end
124
+
125
+ class Metadata
126
+ def self.split_file_contents(content)
127
+ idx = content =~ /\n{3}/m
128
+ metadata = []
133
129
 
134
- if start_index > 0
135
- [raw_lines[0..start_index-3], raw_lines[start_index..-1]]
136
- else
137
- [[], raw_lines]
130
+ if idx
131
+ metadata = content[0..(idx - 1)].split(/\n/)
132
+ valid_metadata?(metadata) ? content = content[(idx + 3)..-1] : metadata = []
138
133
  end
134
+ [self.new(metadata), content]
139
135
  end
140
136
 
141
- def all_lines_are_metadata_lines(lines)
137
+ def self.valid_metadata?(lines)
142
138
  lines.map { |ln| ln.scan(/\A(\w+):?/) }.flatten.
143
- map { |k| @metadata_keys.include?(k) }.uniq == [true]
139
+ map { |k| supported_keys.include?(k) }.uniq == [true]
144
140
  end
145
141
 
146
- def read_metadata(lines)
147
- @metadata = {}
142
+ def self.supported_keys
143
+ %w[mtime encrypted owner]
144
+ end
145
+
146
+ def initialize(lines = [])
147
+ @hash = {}
148
+ @keys = Metadata.supported_keys
149
+ parse_lines(lines)
150
+ end
151
+
152
+ def [](key)
153
+ @hash[key]
154
+ end
155
+
156
+ def []=(key, value)
157
+ raise "Unexpected key: #{key}" unless @keys.include?(key)
158
+
159
+ @hash[key] = value
160
+ end
161
+
162
+ def has?(key)
163
+ @hash.key?(key)
164
+ end
165
+
166
+ def to_s
167
+ @hash.collect { |k, v| "#{k}: #{v}" }.join("\n") + "\n\n\n"
168
+ end
169
+
170
+ def to_h
171
+ @hash
172
+ end
173
+
174
+ private
175
+
176
+ def parse_lines(lines)
148
177
  lines.each do |ln|
149
178
  key, value = ln.split(': ')
150
- @metadata[key] = value if @metadata_keys.include?(key)
179
+ @hash[key] = value.chomp if @keys.include?(key)
151
180
  end
152
181
  end
153
-
154
- def apply_metadata
155
- @modTimeAtLastRead = Time.parse(@metadata['mtime']) if @metadata.keys.include? 'mtime'
156
- end
157
182
  end
158
183
 
159
184
  class Util
160
- def self.raiseIfMTimeNotEqual(mtime_to_compare, file_name)
185
+ def self.raise_if_mtime_not_equal(mtime_to_compare, file_name)
161
186
  # reading the instance .mtime appears to take Windows DST into account,
162
187
  # whereas the static File.mtime(filename) method does not
163
- current_mtime = ::File.open(file_name) do |f|
164
- f.mtime
165
- end
188
+ current_mtime = ::File.open(file_name, &:mtime)
166
189
  compare_read_times!(mtime_to_compare, current_mtime)
167
190
  end
168
191
 
@@ -176,25 +199,20 @@ module ClWiki
176
199
  end
177
200
 
178
201
  def self.dump_time(time)
179
- ''.tap do |s|
180
- s << "#{time}"
202
+ String.new.tap do |s|
203
+ s << time.to_s
181
204
  s << ".#{time.usec}" if time.respond_to?(:usec)
182
205
  end
183
206
  end
184
207
 
185
- def self.convertToNativePath(path)
186
- newpath = path.gsub(/\//, ::File::SEPARATOR)
187
- newpath = newpath.gsub(/\\/, ::File::SEPARATOR)
188
- return newpath
208
+ def self.convert_to_native_path(path)
209
+ path.gsub(%r{/}, ::File::SEPARATOR).gsub(/\\/, ::File::SEPARATOR)
189
210
  end
190
211
  end
191
212
 
192
- class FileError < Exception
213
+ class FileError < RuntimeError
193
214
  end
194
215
 
195
216
  class FileModifiedSinceRead < FileError
196
217
  end
197
-
198
- class FileMustUseWriteNewContent < FileError
199
- end
200
218
  end