From fdba99cb93237f1a324b41155f2202c0a2794171 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Mon, 1 Aug 2005 03:20:36 +0000
Subject: [PATCH 01/84] Branching out instiki-ar (for building an ActiveRecord
backend)
From 21adee88d42e299c524672fb128911e557c19a49 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Tue, 2 Aug 2005 07:58:22 +0000
Subject: [PATCH 02/84] Initial database definitions
---
config/database.yml | 30 ++++++++++++++++++++++++++++++
db/pages.erbsql | 6 ++++++
db/revisions.erbsql | 7 +++++++
db/webs.erbsql | 7 +++++++
lib/db_structure.rb | 32 ++++++++++++++++++++++++++++++++
5 files changed, 82 insertions(+)
create mode 100644 config/database.yml
create mode 100644 db/pages.erbsql
create mode 100644 db/revisions.erbsql
create mode 100644 db/webs.erbsql
create mode 100644 lib/db_structure.rb
diff --git a/config/database.yml b/config/database.yml
new file mode 100644
index 00000000..c21e3f65
--- /dev/null
+++ b/config/database.yml
@@ -0,0 +1,30 @@
+# SQLite is enabled by default. Remember to change the dbfile path.
+production:
+ adapter: sqlite
+ dbfile: /tmp/instiki_prod.db
+
+# Uncomment this section for MySQL:
+# production:
+# adapter: mysql
+# host: localhost
+# database: instiki
+# username: instiki
+# password: pass
+
+# Uncomment this section for PostgreSQL:
+# production:
+# adapter: postgresql
+# host: localhost
+# database: instiki
+# username: instiki
+# password: pass
+
+# The following settings are only used for testing and development.
+development:
+ adapter: sqlite
+ dbfile: /tmp/instiki_dev.db
+
+test:
+ adapter: sqlite
+ dbfile: /tmp/instiki_test.db
+
diff --git a/db/pages.erbsql b/db/pages.erbsql
new file mode 100644
index 00000000..afc57484
--- /dev/null
+++ b/db/pages.erbsql
@@ -0,0 +1,6 @@
+CREATE TABLE pages (
+ id <%= @pk %>,
+ created_at <%= @datetime %> NOT NULL,
+ updated_at <%= @datetime %> NOT NULL,
+ web_id INTEGER NOT NULL
+) <%= create_options %>;
diff --git a/db/revisions.erbsql b/db/revisions.erbsql
new file mode 100644
index 00000000..1639cf2e
--- /dev/null
+++ b/db/revisions.erbsql
@@ -0,0 +1,7 @@
+CREATE TABLE revisions (
+ id <%= @pk %>,
+ created_at <%= @datetime %> NOT NULL,
+ updated_at <%= @datetime %> NOT NULL,
+ page_id INTEGER NOT NULL,
+ content TEXT NOT NULL
+) <%= create_options %>;
diff --git a/db/webs.erbsql b/db/webs.erbsql
new file mode 100644
index 00000000..24ebc04a
--- /dev/null
+++ b/db/webs.erbsql
@@ -0,0 +1,7 @@
+CREATE TABLE pages (
+ id <%= @pk %>,
+ created_at <%= @datetime %> NOT NULL,
+ updated_at <%= @datetime %> NOT NULL,
+ name VARCHAR(60) NOT NULL,
+ address VARCHAR(60) NOT NULL
+) <%= create_options %>;
diff --git a/lib/db_structure.rb b/lib/db_structure.rb
new file mode 100644
index 00000000..0a2c4beb
--- /dev/null
+++ b/lib/db_structure.rb
@@ -0,0 +1,32 @@
+require 'erb'
+
+def create_options
+ if @db == 'mysql'
+ 'ENGINE = ' + (mysql_engine rescue @mysql_engine)
+ end
+end
+
+def db_structure(db)
+ db.downcase!
+ @db = db
+ case db
+ when 'postgresql'
+ @pk = 'SERIAL PRIMARY KEY'
+ @datetime = 'TIMESTAMP'
+ when 'sqlite', 'sqlite3'
+ @pk = 'INTEGER PRIMARY KEY'
+ @datetime = 'DATETIME'
+ when 'mysql'
+ @pk = 'INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY'
+ @datetime = 'DATETIME'
+ @mysql_engine = 'InnoDB'
+ else
+ raise "Unknown db type #{db}"
+ end
+
+ s = ''
+ Dir['db/*.erbsql'].each do |filename|
+ s += ERB.new(File.read(filename)).result
+ end
+ s
+end
From 6d8190c096f7884fa8c998979218b9915c68cbaa Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Tue, 2 Aug 2005 07:59:22 +0000
Subject: [PATCH 03/84] Moved old tests and app/model out of the way
---
app/{models => models-old}/author.rb | 0
app/{models => models-old}/chunks/category.rb | 0
app/{models => models-old}/chunks/chunk.rb | 0
app/{models => models-old}/chunks/engines.rb | 0
app/{models => models-old}/chunks/include.rb | 0
app/{models => models-old}/chunks/literal.rb | 0
app/{models => models-old}/chunks/nowiki.rb | 0
app/{models => models-old}/chunks/test.rb | 0
app/{models => models-old}/chunks/uri.rb | 0
app/{models => models-old}/chunks/wiki.rb | 0
app/{models => models-old}/file_yard.rb | 0
app/{models => models-old}/page.rb | 0
app/{models => models-old}/page_lock.rb | 0
app/{models => models-old}/page_set.rb | 0
app/{models => models-old}/revision.rb | 0
app/{models => models-old}/web.rb | 0
app/{models => models-old}/wiki_content.rb | 0
app/{models => models-old}/wiki_service.rb | 0
app/{models => models-old}/wiki_words.rb | 0
{test => test-old}/all_tests.rb | 0
{test => test-old}/fixtures/rails.gif | Bin
.../functional/admin_controller_test.rb | 0
{test => test-old}/functional/application_test.rb | 0
.../functional/file_controller_test.rb | 0
{test => test-old}/functional/routes_test.rb | 0
.../functional/wiki_controller_test.rb | 0
{test => test-old}/test_helper.rb | 0
{test => test-old}/unit/chunks/category_test.rb | 0
{test => test-old}/unit/chunks/nowiki_test.rb | 0
{test => test-old}/unit/chunks/wiki_test.rb | 0
{test => test-old}/unit/diff_test.rb | 0
{test => test-old}/unit/file_yard_test.rb | 0
{test => test-old}/unit/page_test.rb | 0
{test => test-old}/unit/redcloth_for_tex_test.rb | 0
{test => test-old}/unit/revision_test.rb | 0
{test => test-old}/unit/uri_test.rb | 0
{test => test-old}/unit/web_test.rb | 0
{test => test-old}/unit/wiki_service_test.rb | 0
{test => test-old}/unit/wiki_words_test.rb | 0
{test => test-old}/watir/e2e.rb | 0
40 files changed, 0 insertions(+), 0 deletions(-)
rename app/{models => models-old}/author.rb (100%)
rename app/{models => models-old}/chunks/category.rb (100%)
rename app/{models => models-old}/chunks/chunk.rb (100%)
rename app/{models => models-old}/chunks/engines.rb (100%)
rename app/{models => models-old}/chunks/include.rb (100%)
rename app/{models => models-old}/chunks/literal.rb (100%)
rename app/{models => models-old}/chunks/nowiki.rb (100%)
rename app/{models => models-old}/chunks/test.rb (100%)
rename app/{models => models-old}/chunks/uri.rb (100%)
rename app/{models => models-old}/chunks/wiki.rb (100%)
rename app/{models => models-old}/file_yard.rb (100%)
rename app/{models => models-old}/page.rb (100%)
rename app/{models => models-old}/page_lock.rb (100%)
rename app/{models => models-old}/page_set.rb (100%)
rename app/{models => models-old}/revision.rb (100%)
rename app/{models => models-old}/web.rb (100%)
rename app/{models => models-old}/wiki_content.rb (100%)
rename app/{models => models-old}/wiki_service.rb (100%)
rename app/{models => models-old}/wiki_words.rb (100%)
rename {test => test-old}/all_tests.rb (100%)
rename {test => test-old}/fixtures/rails.gif (100%)
rename {test => test-old}/functional/admin_controller_test.rb (100%)
rename {test => test-old}/functional/application_test.rb (100%)
rename {test => test-old}/functional/file_controller_test.rb (100%)
rename {test => test-old}/functional/routes_test.rb (100%)
rename {test => test-old}/functional/wiki_controller_test.rb (100%)
rename {test => test-old}/test_helper.rb (100%)
rename {test => test-old}/unit/chunks/category_test.rb (100%)
rename {test => test-old}/unit/chunks/nowiki_test.rb (100%)
rename {test => test-old}/unit/chunks/wiki_test.rb (100%)
rename {test => test-old}/unit/diff_test.rb (100%)
rename {test => test-old}/unit/file_yard_test.rb (100%)
rename {test => test-old}/unit/page_test.rb (100%)
rename {test => test-old}/unit/redcloth_for_tex_test.rb (100%)
rename {test => test-old}/unit/revision_test.rb (100%)
rename {test => test-old}/unit/uri_test.rb (100%)
rename {test => test-old}/unit/web_test.rb (100%)
rename {test => test-old}/unit/wiki_service_test.rb (100%)
rename {test => test-old}/unit/wiki_words_test.rb (100%)
rename {test => test-old}/watir/e2e.rb (100%)
diff --git a/app/models/author.rb b/app/models-old/author.rb
similarity index 100%
rename from app/models/author.rb
rename to app/models-old/author.rb
diff --git a/app/models/chunks/category.rb b/app/models-old/chunks/category.rb
similarity index 100%
rename from app/models/chunks/category.rb
rename to app/models-old/chunks/category.rb
diff --git a/app/models/chunks/chunk.rb b/app/models-old/chunks/chunk.rb
similarity index 100%
rename from app/models/chunks/chunk.rb
rename to app/models-old/chunks/chunk.rb
diff --git a/app/models/chunks/engines.rb b/app/models-old/chunks/engines.rb
similarity index 100%
rename from app/models/chunks/engines.rb
rename to app/models-old/chunks/engines.rb
diff --git a/app/models/chunks/include.rb b/app/models-old/chunks/include.rb
similarity index 100%
rename from app/models/chunks/include.rb
rename to app/models-old/chunks/include.rb
diff --git a/app/models/chunks/literal.rb b/app/models-old/chunks/literal.rb
similarity index 100%
rename from app/models/chunks/literal.rb
rename to app/models-old/chunks/literal.rb
diff --git a/app/models/chunks/nowiki.rb b/app/models-old/chunks/nowiki.rb
similarity index 100%
rename from app/models/chunks/nowiki.rb
rename to app/models-old/chunks/nowiki.rb
diff --git a/app/models/chunks/test.rb b/app/models-old/chunks/test.rb
similarity index 100%
rename from app/models/chunks/test.rb
rename to app/models-old/chunks/test.rb
diff --git a/app/models/chunks/uri.rb b/app/models-old/chunks/uri.rb
similarity index 100%
rename from app/models/chunks/uri.rb
rename to app/models-old/chunks/uri.rb
diff --git a/app/models/chunks/wiki.rb b/app/models-old/chunks/wiki.rb
similarity index 100%
rename from app/models/chunks/wiki.rb
rename to app/models-old/chunks/wiki.rb
diff --git a/app/models/file_yard.rb b/app/models-old/file_yard.rb
similarity index 100%
rename from app/models/file_yard.rb
rename to app/models-old/file_yard.rb
diff --git a/app/models/page.rb b/app/models-old/page.rb
similarity index 100%
rename from app/models/page.rb
rename to app/models-old/page.rb
diff --git a/app/models/page_lock.rb b/app/models-old/page_lock.rb
similarity index 100%
rename from app/models/page_lock.rb
rename to app/models-old/page_lock.rb
diff --git a/app/models/page_set.rb b/app/models-old/page_set.rb
similarity index 100%
rename from app/models/page_set.rb
rename to app/models-old/page_set.rb
diff --git a/app/models/revision.rb b/app/models-old/revision.rb
similarity index 100%
rename from app/models/revision.rb
rename to app/models-old/revision.rb
diff --git a/app/models/web.rb b/app/models-old/web.rb
similarity index 100%
rename from app/models/web.rb
rename to app/models-old/web.rb
diff --git a/app/models/wiki_content.rb b/app/models-old/wiki_content.rb
similarity index 100%
rename from app/models/wiki_content.rb
rename to app/models-old/wiki_content.rb
diff --git a/app/models/wiki_service.rb b/app/models-old/wiki_service.rb
similarity index 100%
rename from app/models/wiki_service.rb
rename to app/models-old/wiki_service.rb
diff --git a/app/models/wiki_words.rb b/app/models-old/wiki_words.rb
similarity index 100%
rename from app/models/wiki_words.rb
rename to app/models-old/wiki_words.rb
diff --git a/test/all_tests.rb b/test-old/all_tests.rb
similarity index 100%
rename from test/all_tests.rb
rename to test-old/all_tests.rb
diff --git a/test/fixtures/rails.gif b/test-old/fixtures/rails.gif
similarity index 100%
rename from test/fixtures/rails.gif
rename to test-old/fixtures/rails.gif
diff --git a/test/functional/admin_controller_test.rb b/test-old/functional/admin_controller_test.rb
similarity index 100%
rename from test/functional/admin_controller_test.rb
rename to test-old/functional/admin_controller_test.rb
diff --git a/test/functional/application_test.rb b/test-old/functional/application_test.rb
similarity index 100%
rename from test/functional/application_test.rb
rename to test-old/functional/application_test.rb
diff --git a/test/functional/file_controller_test.rb b/test-old/functional/file_controller_test.rb
similarity index 100%
rename from test/functional/file_controller_test.rb
rename to test-old/functional/file_controller_test.rb
diff --git a/test/functional/routes_test.rb b/test-old/functional/routes_test.rb
similarity index 100%
rename from test/functional/routes_test.rb
rename to test-old/functional/routes_test.rb
diff --git a/test/functional/wiki_controller_test.rb b/test-old/functional/wiki_controller_test.rb
similarity index 100%
rename from test/functional/wiki_controller_test.rb
rename to test-old/functional/wiki_controller_test.rb
diff --git a/test/test_helper.rb b/test-old/test_helper.rb
similarity index 100%
rename from test/test_helper.rb
rename to test-old/test_helper.rb
diff --git a/test/unit/chunks/category_test.rb b/test-old/unit/chunks/category_test.rb
similarity index 100%
rename from test/unit/chunks/category_test.rb
rename to test-old/unit/chunks/category_test.rb
diff --git a/test/unit/chunks/nowiki_test.rb b/test-old/unit/chunks/nowiki_test.rb
similarity index 100%
rename from test/unit/chunks/nowiki_test.rb
rename to test-old/unit/chunks/nowiki_test.rb
diff --git a/test/unit/chunks/wiki_test.rb b/test-old/unit/chunks/wiki_test.rb
similarity index 100%
rename from test/unit/chunks/wiki_test.rb
rename to test-old/unit/chunks/wiki_test.rb
diff --git a/test/unit/diff_test.rb b/test-old/unit/diff_test.rb
similarity index 100%
rename from test/unit/diff_test.rb
rename to test-old/unit/diff_test.rb
diff --git a/test/unit/file_yard_test.rb b/test-old/unit/file_yard_test.rb
similarity index 100%
rename from test/unit/file_yard_test.rb
rename to test-old/unit/file_yard_test.rb
diff --git a/test/unit/page_test.rb b/test-old/unit/page_test.rb
similarity index 100%
rename from test/unit/page_test.rb
rename to test-old/unit/page_test.rb
diff --git a/test/unit/redcloth_for_tex_test.rb b/test-old/unit/redcloth_for_tex_test.rb
similarity index 100%
rename from test/unit/redcloth_for_tex_test.rb
rename to test-old/unit/redcloth_for_tex_test.rb
diff --git a/test/unit/revision_test.rb b/test-old/unit/revision_test.rb
similarity index 100%
rename from test/unit/revision_test.rb
rename to test-old/unit/revision_test.rb
diff --git a/test/unit/uri_test.rb b/test-old/unit/uri_test.rb
similarity index 100%
rename from test/unit/uri_test.rb
rename to test-old/unit/uri_test.rb
diff --git a/test/unit/web_test.rb b/test-old/unit/web_test.rb
similarity index 100%
rename from test/unit/web_test.rb
rename to test-old/unit/web_test.rb
diff --git a/test/unit/wiki_service_test.rb b/test-old/unit/wiki_service_test.rb
similarity index 100%
rename from test/unit/wiki_service_test.rb
rename to test-old/unit/wiki_service_test.rb
diff --git a/test/unit/wiki_words_test.rb b/test-old/unit/wiki_words_test.rb
similarity index 100%
rename from test/unit/wiki_words_test.rb
rename to test-old/unit/wiki_words_test.rb
diff --git a/test/watir/e2e.rb b/test-old/watir/e2e.rb
similarity index 100%
rename from test/watir/e2e.rb
rename to test-old/watir/e2e.rb
From 1b8baa3d03c1ca13bdefe1f24794998c169704d7 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Tue, 2 Aug 2005 08:56:09 +0000
Subject: [PATCH 04/84] Some infrastructure for AR and accompanying unit tests
---
app/model/page.rb | 4 ++
app/model/revision.rb | 3 +
app/model/web.rb | 3 +
config/database.yml | 6 +-
config/environment.rb | 115 ++++++++++++++++++++----------------
config/environments/test.rb | 2 -
db/webs.erbsql | 2 +-
lib/active_record_stub.rb | 31 ----------
lib/db_structure.rb | 2 +-
script/create_db | 24 ++++++++
script/debug_storage | 97 ------------------------------
test/fixtures/pages.yml | 2 +
test/fixtures/revisions.yml | 2 +
test/fixtures/webs.yml | 2 +
test/test_helper.rb | 26 ++++++++
test/unit/page_test.rb | 7 +++
test/unit/revision_test.rb | 7 +++
test/unit/web_test.rb | 7 +++
18 files changed, 155 insertions(+), 187 deletions(-)
create mode 100644 app/model/page.rb
create mode 100644 app/model/revision.rb
create mode 100644 app/model/web.rb
delete mode 100644 lib/active_record_stub.rb
create mode 100644 script/create_db
delete mode 100644 script/debug_storage
create mode 100644 test/fixtures/pages.yml
create mode 100644 test/fixtures/revisions.yml
create mode 100644 test/fixtures/webs.yml
create mode 100644 test/test_helper.rb
create mode 100644 test/unit/page_test.rb
create mode 100644 test/unit/revision_test.rb
create mode 100644 test/unit/web_test.rb
diff --git a/app/model/page.rb b/app/model/page.rb
new file mode 100644
index 00000000..5f85c8ab
--- /dev/null
+++ b/app/model/page.rb
@@ -0,0 +1,4 @@
+class Page < ActiveRecord::Base
+ belongs_to :web
+ has_many :pages
+end
\ No newline at end of file
diff --git a/app/model/revision.rb b/app/model/revision.rb
new file mode 100644
index 00000000..017b3543
--- /dev/null
+++ b/app/model/revision.rb
@@ -0,0 +1,3 @@
+class Revision < ActiveRecord::Base
+ belongs_to :page
+end
\ No newline at end of file
diff --git a/app/model/web.rb b/app/model/web.rb
new file mode 100644
index 00000000..2c31bf8f
--- /dev/null
+++ b/app/model/web.rb
@@ -0,0 +1,3 @@
+class Web < ActiveRecord::Base
+ has_many :pages
+end
\ No newline at end of file
diff --git a/config/database.yml b/config/database.yml
index c21e3f65..1233b7e3 100644
--- a/config/database.yml
+++ b/config/database.yml
@@ -1,6 +1,6 @@
# SQLite is enabled by default. Remember to change the dbfile path.
production:
- adapter: sqlite
+ adapter: sqlite3
dbfile: /tmp/instiki_prod.db
# Uncomment this section for MySQL:
@@ -21,10 +21,10 @@ production:
# The following settings are only used for testing and development.
development:
- adapter: sqlite
+ adapter: sqlite3
dbfile: /tmp/instiki_dev.db
test:
- adapter: sqlite
+ adapter: sqlite3
dbfile: /tmp/instiki_test.db
diff --git a/config/environment.rb b/config/environment.rb
index bc3ac725..589025c8 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -1,5 +1,10 @@
-if RUBY_VERSION < '1.8.1'
- puts 'Instiki requires Ruby 1.8.1+'
+# Load the Rails framework and configure your application.
+# You can include your own configuration at the end of this file.
+#
+# Be sure to restart your webserver when you modify this file.
+
+if RUBY_VERSION < '1.8.2'
+ puts 'Instiki requires Ruby 1.8.2+'
exit
end
@@ -7,76 +12,82 @@ end
$KCODE = 'u'
require 'jcode'
-RAILS_ROOT = File.expand_path(File.dirname(__FILE__) + '/../') unless defined? RAILS_ROOT
-RAILS_ENV = ENV['RAILS_ENV'] || 'production' unless defined? RAILS_ENV
+# The path to the root directory of your application.
+RAILS_ROOT = File.expand_path(File.dirname(__FILE__) + '/../')
-unless defined? ADDITIONAL_LOAD_PATHS
- # Mocks first.
- ADDITIONAL_LOAD_PATHS = ["#{RAILS_ROOT}/test/mocks/#{RAILS_ENV}"]
+# The environment your application is currently running. Don't set
+# this here; put it in your webserver's configuration as the RAILS_ENV
+# environment variable instead.
+#
+# See config/environments/*.rb for environment-specific configuration.
+RAILS_ENV = ENV['RAILS_ENV'] || 'development'
- # Then model subdirectories.
- ADDITIONAL_LOAD_PATHS.concat(Dir["#{RAILS_ROOT}/app/models/[_a-z]*"])
- ADDITIONAL_LOAD_PATHS.concat(Dir["#{RAILS_ROOT}/components/[_a-z]*"])
+# Load the Rails framework. Mock classes for testing come first.
+ADDITIONAL_LOAD_PATHS = ["#{RAILS_ROOT}/test/mocks/#{RAILS_ENV}"]
- # Followed by the standard includes.
- ADDITIONAL_LOAD_PATHS.concat %w(
- app
- app/models
- app/controllers
- app/helpers
- app/apis
- components
- config
- lib
- vendor
- vendor/rails/railties
- vendor/rails/railties/lib
- vendor/rails/actionpack/lib
- vendor/rails/activesupport/lib
- vendor/rails/activerecord/lib
- vendor/rails/actionmailer/lib
- vendor/rails/actionwebservice/lib
- vendor/madeleine-0.7.1/lib
- vendor/RedCloth-3.0.3/lib
- vendor/rubyzip-0.5.8/lib
- ).map { |dir| "#{File.expand_path(File.join(RAILS_ROOT, dir))}"
- }.delete_if { |dir| not File.exist?(dir) }
+# Then model subdirectories.
+ADDITIONAL_LOAD_PATHS.concat(Dir["#{RAILS_ROOT}/app/models/[_a-z]*"])
+ADDITIONAL_LOAD_PATHS.concat(Dir["#{RAILS_ROOT}/components/[_a-z]*"])
- # Prepend to $LOAD_PATH
- ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) }
-end
+# Followed by the standard includes.
+ADDITIONAL_LOAD_PATHS.concat %w(
+ app
+ app/models
+ app/controllers
+ app/helpers
+ app/apis
+ components
+ config
+ lib
+ vendor
+ vendor/rails/railties
+ vendor/rails/railties/lib
+ vendor/rails/actionpack/lib
+ vendor/rails/activesupport/lib
+ vendor/rails/activerecord/lib
+ vendor/rails/actionmailer/lib
+ vendor/rails/actionwebservice/lib
+ vendor/RedCloth-3.0.3/lib
+ vendor/rubyzip-0.5.8/lib
+).map { |dir| "#{RAILS_ROOT}/#{dir}" }.select { |dir| File.directory?(dir) }
+
+# Prepend to $LOAD_PATH
+ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) }
# Require Rails libraries.
require 'rubygems' unless File.directory?("#{RAILS_ROOT}/vendor/rails")
require 'active_support'
+require 'active_record'
require 'action_controller'
-require_dependency 'instiki_errors'
-require_dependency 'active_record_stub'
-
-# Environment specific configuration
+# Environment-specific configuration.
require_dependency "environments/#{RAILS_ENV}"
+ActiveRecord::Base.configurations = File.open("#{RAILS_ROOT}/config/database.yml") { |f| YAML::load(f) }
+ActiveRecord::Base.establish_connection
# Configure defaults if the included environment did not.
-unless defined? RAILS_DEFAULT_LOGGER
+begin
+ RAILS_DEFAULT_LOGGER = Logger.new("#{RAILS_ROOT}/log/#{RAILS_ENV}.log")
+ RAILS_DEFAULT_LOGGER.level = (RAILS_ENV == 'production' ? Logger::INFO : Logger::DEBUG)
+rescue StandardError
RAILS_DEFAULT_LOGGER = Logger.new(STDERR)
- ActionController::Base.logger ||= RAILS_DEFAULT_LOGGER
- if $instiki_debug_logging
- RAILS_DEFAULT_LOGGER.level = Logger::DEBUG
- ActionController::Base.logger.level = Logger::DEBUG
- else
- RAILS_DEFAULT_LOGGER.level = Logger::INFO
- ActionController::Base.logger.level = Logger::INFO
- end
+ RAILS_DEFAULT_LOGGER.level = Logger::WARN
+ RAILS_DEFAULT_LOGGER.warn(
+ "Rails Error: Unable to access log file. Please ensure that log/#{RAILS_ENV}.log exists and is chmod 0666. " +
+ "The log level has been raised to WARN and the output directed to STDERR until the problem is fixed."
+ )
end
-ActionController::Base.template_root ||= "#{RAILS_ROOT}/app/views/"
+[ActiveRecord, ActionController, ActionMailer].each { |mod| mod::Base.logger ||= RAILS_DEFAULT_LOGGER }
+[ActionController, ActionMailer].each { |mod| mod::Base.template_root ||= "#{RAILS_ROOT}/app/views/" }
+
+# Set up routes.
ActionController::Routing::Routes.reload
+
Controllers = Dependencies::LoadingModule.root(
File.join(RAILS_ROOT, 'app', 'controllers'),
File.join(RAILS_ROOT, 'components')
)
-require 'wiki_service'
-Socket.do_not_reverse_lookup = true
+require_dependency 'instiki_errors'
diff --git a/config/environments/test.rb b/config/environments/test.rb
index ece6e9cf..fac509a1 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -12,6 +12,4 @@ unless defined? TEST_LOGGER
TEST_LOGGER = ActionController::Base.logger = Logger.new(log_name)
$instiki_debug_logging = true
-
- WikiService.storage_path = RAILS_ROOT + '/storage/test/'
end
diff --git a/db/webs.erbsql b/db/webs.erbsql
index 24ebc04a..bbb9758c 100644
--- a/db/webs.erbsql
+++ b/db/webs.erbsql
@@ -1,4 +1,4 @@
-CREATE TABLE pages (
+CREATE TABLE webs (
id <%= @pk %>,
created_at <%= @datetime %> NOT NULL,
updated_at <%= @datetime %> NOT NULL,
diff --git a/lib/active_record_stub.rb b/lib/active_record_stub.rb
deleted file mode 100644
index 126beb0b..00000000
--- a/lib/active_record_stub.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# This project uses Railties, which has an external dependency on ActiveRecord
-# Since ActiveRecord may not be present in Instiki runtime environment, this
-# file provides a stub replacement for it
-
-module ActiveRecord
- class Base
-
- # dependency in railties/lib/dispatcher.rb
- def self.reset_column_information_and_inheritable_attributes_for_all_subclasses
- # noop
- end
-
- # dependency in actionpack/lib/action_controller/benchmarking.rb
- def self.connected?
- false
- end
-
- # dependency in actionpack/lib/action_controller/benchmarking.rb
- def self.connection
- return ConnectionStub
- end
-
- end
-
- module ConnectionStub
- def self.reset_runtime
- 0
- end
- end
-
-end
diff --git a/lib/db_structure.rb b/lib/db_structure.rb
index 0a2c4beb..c7b58c33 100644
--- a/lib/db_structure.rb
+++ b/lib/db_structure.rb
@@ -25,7 +25,7 @@ def db_structure(db)
end
s = ''
- Dir['db/*.erbsql'].each do |filename|
+ Dir[RAILS_ROOT + '/db/*.erbsql'].each do |filename|
s += ERB.new(File.read(filename)).result
end
s
diff --git a/script/create_db b/script/create_db
new file mode 100644
index 00000000..b421fb8c
--- /dev/null
+++ b/script/create_db
@@ -0,0 +1,24 @@
+#!/usr/bin/env ruby
+
+APP_ROOT = File.expand_path(File.dirname(__FILE__)) + '/../'
+
+require APP_ROOT + 'config/environment'
+require 'db_structure'
+
+config = ActiveRecord::Base.configurations
+
+['production', 'test', 'development'].each do |target|
+ begin
+ ENV['RAILS_ENV'] = target
+ load APP_ROOT + 'config/environment.rb'
+ puts "Creating tables for #{target}..."
+
+ db_structure(config[target]['adapter']).split(/\s*;\s*/).each do |sql|
+ ActiveRecord::Base.connection.execute(sql)
+ end
+
+ puts "done."
+ rescue => e
+ puts "failed: " + e.inspect
+ end
+end
diff --git a/script/debug_storage b/script/debug_storage
deleted file mode 100644
index 8b0060f0..00000000
--- a/script/debug_storage
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/usr/bin/ruby
-
-=begin
-The purpose of this script is to help people poke around in the Madeleine storage.
-
-Two caveats:
-1. You MUST be a reasonably good Ruby programmer to use it successfully for anything non-trivial.
-2. It's very easy to screw up something by poking in the storage internals. If you do, please
- undo your changes by deleting the most recent snapshot(s) and don't ask for help.
-
-Usage example:
-
-E:\eclipse\workspace\instiki\script>irb
-irb(main):001:0> load 'debug_storage'
-Enter path to storage [E:/eclipse/workspace/instiki/storage/2500]:
-Loading storage from the default storage path (E:/eclipse/workspace/instiki/storage/2500)
-Instiki storage from E:/eclipse/workspace/instiki/storage/2500 is loaded.
-Access it via global variable $wiki.
-Happy poking!
-=> true
-irb(main):003:0> $wiki.system
-=> {"password"=>"foo"}
-irb(main):005:0> $wiki.system['password'] = 'bar'
-=> "bar"
-irb(main):006:0> $wiki.webs.keys
-=> ["wiki1", "wiki2"]
-irb(main):007:0> $wiki.webs['wiki1'].password = 'the_password'
-=> "the_password"
-irb(main):008:0> WikiService::snapshot
-=> []
-
-
-Things that are possible:
-
-# cleaning old revisions
-$wiki.webs['wiki'].pages['HomePage'].revisions = $wiki.webs['wiki'].pages['HomePage'].revisions[-1..-1]
-
-# Changing contents of a revision
-$wiki.webs['wiki'].pages['HomePage'].revisions[-1] = 'new content'
-
-# Checking that all pages can be rendered by the markup engine
-$wiki.webs['wiki'].pages.each_pair do |name, page|
- page.revisions.each_with_index do |revision, i|
- begin
- revision.display_content
- rescue =>
- puts "Error when rendering revision ##{i} of page #{name.inspect}:"
- puts e.message
- puts e.backtrace.join("\n")
- end
-end
-=end
-
-require 'fileutils'
-require 'optparse'
-require 'webrick'
-
-default_storage_path = File.expand_path(File.dirname(__FILE__) + "/../storage/2500")
-
-print "Enter path to storage [#{default_storage_path}]: "
-storage_path = gets.chomp
-if storage_path.empty?
- storage_path = default_storage_path
- puts "Loading storage from the default storage path (#{storage_path})"
-else
- puts "Loading storage from the path you entered (#{storage_path})"
-end
-
-unless File.directory?(storage_path) and not
- (Dir["#{storage_path}/*.snapshot"] + Dir["#{storage_path}/*.command_log"]).empty?
- raise "Found no storage at #{storage_path}"
-end
-
-RAILS_ROOT = File.expand_path(File.dirname(__FILE__) + '/../') unless defined? RAILS_ROOT
-
-unless defined? ADDITIONAL_LOAD_PATHS
- ADDITIONAL_LOAD_PATHS = %w(
- app/models
- lib
- vendor/madeleine-0.7.1/lib
- vendor/RedCloth-3.0.3/lib
- vendor/rubyzip-0.5.8/lib
- ).map { |dir| "#{File.expand_path(File.join(RAILS_ROOT, dir))}"
- }.delete_if { |dir| not File.exist?(dir) }
-
- # Prepend to $LOAD_PATH
- ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) }
-end
-
-require 'wiki_service'
-
-WikiService.storage_path = storage_path
-$wiki = WikiService.instance
-puts "Instiki storage from #{storage_path} is loaded."
-puts 'Access it via global variable $wiki.'
-puts 'Happy poking!'
-nil
diff --git a/test/fixtures/pages.yml b/test/fixtures/pages.yml
new file mode 100644
index 00000000..9f856f2a
--- /dev/null
+++ b/test/fixtures/pages.yml
@@ -0,0 +1,2 @@
+home_page:
+ id: 1
diff --git a/test/fixtures/revisions.yml b/test/fixtures/revisions.yml
new file mode 100644
index 00000000..6538429d
--- /dev/null
+++ b/test/fixtures/revisions.yml
@@ -0,0 +1,2 @@
+home_page_first_revision:
+ id: 1
diff --git a/test/fixtures/webs.yml b/test/fixtures/webs.yml
new file mode 100644
index 00000000..8c4a2778
--- /dev/null
+++ b/test/fixtures/webs.yml
@@ -0,0 +1,2 @@
+test_wiki:
+ id: 1
diff --git a/test/test_helper.rb b/test/test_helper.rb
new file mode 100644
index 00000000..19219ce7
--- /dev/null
+++ b/test/test_helper.rb
@@ -0,0 +1,26 @@
+ENV["RAILS_ENV"] = "test"
+
+# Expand the path to environment so that Ruby does not load it multiple times
+# File.expand_path can be removed if Ruby 1.9 is in use.
+require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
+require 'application'
+
+require 'test/unit'
+require 'active_record/fixtures'
+require 'action_controller/test_process'
+require 'action_web_service/test_invoke'
+require 'breakpoint'
+
+Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
+
+class Test::Unit::TestCase
+ # Turn these on to use transactional fixtures with table_name(:fixture_name) instantiation of fixtures
+ # self.use_transactional_fixtures = true
+ # self.use_instantiated_fixtures = false
+
+ def create_fixtures(*table_names)
+ Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures", table_names)
+ end
+
+ # Add more helper methods to be used by all tests here...
+end
\ No newline at end of file
diff --git a/test/unit/page_test.rb b/test/unit/page_test.rb
new file mode 100644
index 00000000..8af94246
--- /dev/null
+++ b/test/unit/page_test.rb
@@ -0,0 +1,7 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class PageTest < Test::Unit::TestCase
+
+ fixtures 'webs', 'pages', 'revisions'
+
+end
diff --git a/test/unit/revision_test.rb b/test/unit/revision_test.rb
new file mode 100644
index 00000000..0024c6b3
--- /dev/null
+++ b/test/unit/revision_test.rb
@@ -0,0 +1,7 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class RevisionTest < Test::Unit::TestCase
+
+ fixtures 'webs', 'pages', 'revisions'
+
+end
diff --git a/test/unit/web_test.rb b/test/unit/web_test.rb
new file mode 100644
index 00000000..2e504e0c
--- /dev/null
+++ b/test/unit/web_test.rb
@@ -0,0 +1,7 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class WebTest < Test::Unit::TestCase
+
+ fixtures 'webs', 'pages', 'revisions'
+
+end
From 125cc37135dabc6cc8d3f8ef1c0ea12a0b2372ff Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Tue, 2 Aug 2005 08:59:57 +0000
Subject: [PATCH 05/84] Added non-nullable fields to fixtures
---
test/fixtures/pages.yml | 3 +++
test/fixtures/revisions.yml | 4 ++++
test/fixtures/webs.yml | 4 ++++
3 files changed, 11 insertions(+)
diff --git a/test/fixtures/pages.yml b/test/fixtures/pages.yml
index 9f856f2a..2c62113c 100644
--- a/test/fixtures/pages.yml
+++ b/test/fixtures/pages.yml
@@ -1,2 +1,5 @@
home_page:
id: 1
+ created_at: 2004-08-01
+ updated_at: 2005-08-01
+ web_id: 1
\ No newline at end of file
diff --git a/test/fixtures/revisions.yml b/test/fixtures/revisions.yml
index 6538429d..9d43eb26 100644
--- a/test/fixtures/revisions.yml
+++ b/test/fixtures/revisions.yml
@@ -1,2 +1,6 @@
home_page_first_revision:
id: 1
+ created_at: 2004-08-01
+ updated_at: 2005-08-01
+ page_id: 1
+ content: some text
\ No newline at end of file
diff --git a/test/fixtures/webs.yml b/test/fixtures/webs.yml
index 8c4a2778..7276bb65 100644
--- a/test/fixtures/webs.yml
+++ b/test/fixtures/webs.yml
@@ -1,2 +1,6 @@
test_wiki:
id: 1
+ created_at: 2004-08-01
+ updated_at: 2005-08-01
+ name: wiki
+ address: wiki
\ No newline at end of file
From 6fb0102a5ad9c4430aa7bfee7c15c649d0d2fd6d Mon Sep 17 00:00:00 2001
From: Rick Okin
Date: Mon, 8 Aug 2005 04:32:03 +0000
Subject: [PATCH 06/84] Just checking authentication
---
README | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README b/README
index adbaaaf1..b5df8534 100755
--- a/README
+++ b/README
@@ -66,3 +66,5 @@ Make sure that you always launch Instiki from the same working directory, or spe
Author:: David Heinemeier Hansson
Email:: david@loudthinking.com
Weblog:: http://www.loudthinking.com
+
+
From e4ecb406bf3535639d03285092548b3276937d30 Mon Sep 17 00:00:00 2001
From: Rick Okin
Date: Tue, 9 Aug 2005 01:18:00 +0000
Subject: [PATCH 07/84] renamed model directory
---
app/{model => models}/page.rb | 0
app/{model => models}/revision.rb | 0
app/{model => models}/web.rb | 0
3 files changed, 0 insertions(+), 0 deletions(-)
rename app/{model => models}/page.rb (100%)
rename app/{model => models}/revision.rb (100%)
rename app/{model => models}/web.rb (100%)
diff --git a/app/model/page.rb b/app/models/page.rb
similarity index 100%
rename from app/model/page.rb
rename to app/models/page.rb
diff --git a/app/model/revision.rb b/app/models/revision.rb
similarity index 100%
rename from app/model/revision.rb
rename to app/models/revision.rb
diff --git a/app/model/web.rb b/app/models/web.rb
similarity index 100%
rename from app/model/web.rb
rename to app/models/web.rb
From 2eb01cd5756912e5da973ecd6ebe249d468bc934 Mon Sep 17 00:00:00 2001
From: Rick Okin
Date: Tue, 9 Aug 2005 01:23:11 +0000
Subject: [PATCH 08/84] moved some tests over
---
test-old/functional/routes_test.rb => test/functional | 0
test-old/unit/diff_test.rb => test/uni | 0
{test-old => test}/unit/chunks/category_test.rb | 0
{test-old => test}/unit/chunks/nowiki_test.rb | 0
{test-old => test}/unit/chunks/wiki_test.rb | 0
{test-old => test}/unit/file_yard_test.rb | 0
{test-old => test}/unit/redcloth_for_tex_test.rb | 0
{test-old => test}/unit/uri_test.rb | 0
{test-old => test}/unit/wiki_words_test.rb | 0
9 files changed, 0 insertions(+), 0 deletions(-)
rename test-old/functional/routes_test.rb => test/functional (100%)
rename test-old/unit/diff_test.rb => test/uni (100%)
rename {test-old => test}/unit/chunks/category_test.rb (100%)
rename {test-old => test}/unit/chunks/nowiki_test.rb (100%)
rename {test-old => test}/unit/chunks/wiki_test.rb (100%)
rename {test-old => test}/unit/file_yard_test.rb (100%)
rename {test-old => test}/unit/redcloth_for_tex_test.rb (100%)
rename {test-old => test}/unit/uri_test.rb (100%)
rename {test-old => test}/unit/wiki_words_test.rb (100%)
diff --git a/test-old/functional/routes_test.rb b/test/functional
similarity index 100%
rename from test-old/functional/routes_test.rb
rename to test/functional
diff --git a/test-old/unit/diff_test.rb b/test/uni
similarity index 100%
rename from test-old/unit/diff_test.rb
rename to test/uni
diff --git a/test-old/unit/chunks/category_test.rb b/test/unit/chunks/category_test.rb
similarity index 100%
rename from test-old/unit/chunks/category_test.rb
rename to test/unit/chunks/category_test.rb
diff --git a/test-old/unit/chunks/nowiki_test.rb b/test/unit/chunks/nowiki_test.rb
similarity index 100%
rename from test-old/unit/chunks/nowiki_test.rb
rename to test/unit/chunks/nowiki_test.rb
diff --git a/test-old/unit/chunks/wiki_test.rb b/test/unit/chunks/wiki_test.rb
similarity index 100%
rename from test-old/unit/chunks/wiki_test.rb
rename to test/unit/chunks/wiki_test.rb
diff --git a/test-old/unit/file_yard_test.rb b/test/unit/file_yard_test.rb
similarity index 100%
rename from test-old/unit/file_yard_test.rb
rename to test/unit/file_yard_test.rb
diff --git a/test-old/unit/redcloth_for_tex_test.rb b/test/unit/redcloth_for_tex_test.rb
similarity index 100%
rename from test-old/unit/redcloth_for_tex_test.rb
rename to test/unit/redcloth_for_tex_test.rb
diff --git a/test-old/unit/uri_test.rb b/test/unit/uri_test.rb
similarity index 100%
rename from test-old/unit/uri_test.rb
rename to test/unit/uri_test.rb
diff --git a/test-old/unit/wiki_words_test.rb b/test/unit/wiki_words_test.rb
similarity index 100%
rename from test-old/unit/wiki_words_test.rb
rename to test/unit/wiki_words_test.rb
From 64b9a5c747733662e1f1236c4b569e79109a9ad6 Mon Sep 17 00:00:00 2001
From: Rick Okin
Date: Tue, 9 Aug 2005 01:24:44 +0000
Subject: [PATCH 09/84] fixing bad filename
---
test/{functional => routes_test.rb} | 0
test/{uni => unit/diff_test.rb} | 0
2 files changed, 0 insertions(+), 0 deletions(-)
rename test/{functional => routes_test.rb} (100%)
rename test/{uni => unit/diff_test.rb} (100%)
diff --git a/test/functional b/test/routes_test.rb
similarity index 100%
rename from test/functional
rename to test/routes_test.rb
diff --git a/test/uni b/test/unit/diff_test.rb
similarity index 100%
rename from test/uni
rename to test/unit/diff_test.rb
From 8c331d101975769ed8b66c4df29fc0eee196a587 Mon Sep 17 00:00:00 2001
From: Rick Okin
Date: Tue, 9 Aug 2005 01:28:19 +0000
Subject: [PATCH 10/84] moved old test stuff
---
test-old/all_tests.rb | 9 -
test-old/test_helper.rb | 129 -------
test-old/unit/page_test.rb | 89 -----
test-old/unit/revision_test.rb | 335 ------------------
test-old/unit/web_test.rb | 165 ---------
test-old/unit/wiki_service_test.rb | 129 -------
{test-old => test}/fixtures/rails.gif | Bin
.../functional/admin_controller_test.rb | 0
.../functional/application_test.rb | 0
.../functional/file_controller_test.rb | 0
test/{ => functional}/routes_test.rb | 0
.../functional/wiki_controller_test.rb | 0
{test-old => test}/watir/e2e.rb | 0
13 files changed, 856 deletions(-)
delete mode 100755 test-old/all_tests.rb
delete mode 100644 test-old/test_helper.rb
delete mode 100755 test-old/unit/page_test.rb
delete mode 100755 test-old/unit/revision_test.rb
delete mode 100755 test-old/unit/web_test.rb
delete mode 100755 test-old/unit/wiki_service_test.rb
rename {test-old => test}/fixtures/rails.gif (100%)
rename {test-old => test}/functional/admin_controller_test.rb (100%)
rename {test-old => test}/functional/application_test.rb (100%)
rename {test-old => test}/functional/file_controller_test.rb (100%)
rename test/{ => functional}/routes_test.rb (100%)
rename {test-old => test}/functional/wiki_controller_test.rb (100%)
rename {test-old => test}/watir/e2e.rb (100%)
diff --git a/test-old/all_tests.rb b/test-old/all_tests.rb
deleted file mode 100755
index 023ee389..00000000
--- a/test-old/all_tests.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-require 'test_helper'
-require 'find'
-
-test_root = File.dirname(__FILE__)
-Find.find(test_root) { |path|
- if File.file?(path) and path =~ /.*_test\.rb$/
- load path
- end
-}
diff --git a/test-old/test_helper.rb b/test-old/test_helper.rb
deleted file mode 100644
index fe8c1e29..00000000
--- a/test-old/test_helper.rb
+++ /dev/null
@@ -1,129 +0,0 @@
-ENV['RAILS_ENV'] = 'test'
-require File.expand_path(File.dirname(__FILE__) + '/../config/environment')
-require 'application'
-require 'test/unit'
-require 'breakpoint'
-require 'action_controller/test_process'
-
-# Uncomment this variable to have assert_success check that response bodies are valid XML
-$validate_xml_in_assert_success = true
-
-# Convenient setup method for Test::Unit::TestCase
-class Test::Unit::TestCase
-
- private
-
- def setup_controller_test(controller_class = nil, host = nil)
- if controller_class
- @controller = controller_class.new
- elsif self.class.to_s =~ /^(\w+Controller)Test$/
- @controller = Object::const_get($1).new
- else
- raise "Cannot derive the name of controller under test from class name #{self.class}"
- end
- @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
- @request.host = host || 'localhost'
- return @request, @response
- end
-
- # Wiki fixture for tests
-
- def setup_test_wiki
- @wiki = ApplicationController.wiki = WikiServiceWithNoPersistence.new
- @web = @wiki.create_web('Test Wiki 1', 'wiki1')
- @home = @wiki.write_page('wiki1', 'HomePage', 'First revision of the HomePage end', Time.now,
- Author.new('AnAuthor', '127.0.0.1'))
- end
-
- def setup_wiki_with_three_pages
- @oak = @wiki.write_page('wiki1', 'Oak',
- "All about oak.\n" +
- "category: trees",
- 5.minutes.ago, Author.new('TreeHugger', '127.0.0.2'))
- @elephant = @wiki.write_page('wiki1', 'Elephant',
- "All about elephants.\n" +
- "category: animals",
- 10.minutes.ago, Author.new('Guest', '127.0.0.2'))
- end
-
- def setup_wiki_with_30_pages
- (1..30).each { |i|
- @wiki.write_page('wiki1', "page#{i}", "Test page #{i}\ncategory: test",
- Time.local(1976, 10, i, 12, 00, 00), Author.new('Dema', '127.0.0.2'))
- }
- end
-
- def tear_down_wiki
- ApplicationController.wiki = nil
- end
-
-end
-
-class WikiServiceWithNoPersistence
- include AbstractWikiService
- def initialize
- init_wiki_service
- end
-
- def storage_path
- RAILS_ROOT + '/storage/test/'
- end
-end
-
-
-# This module is to be included in unit tests that involve matching chunks.
-# It provides a easy way to test whether a chunk matches a particular string
-# and any the values of any fields that should be set after a match.
-class ContentStub < String
- include ChunkManager
- def initialize(str)
- super
- init_chunk_manager
- end
- def page_link(*); end
-end
-
-module ChunkMatch
-
- # Asserts a number of tests for the given type and text.
- def match(chunk_type, test_text, expected_chunk_state)
- if chunk_type.respond_to? :pattern
- assert_match(chunk_type.pattern, test_text)
- end
-
- content = ContentStub.new(test_text)
- chunk_type.apply_to(content)
-
- # Test if requested parts are correct.
- expected_chunk_state.each_pair do |a_method, expected_value|
- assert content.chunks.last.kind_of?(chunk_type)
- assert_respond_to(content.chunks.last, a_method)
- assert_equal(expected_value, content.chunks.last.send(a_method.to_sym),
- "Wrong #{a_method} value")
- end
- end
-
- # Asserts that test_text doesn't match the chunk_type
- def no_match(chunk_type, test_text)
- if chunk_type.respond_to? :pattern
- assert_no_match(chunk_type.pattern, test_text)
- end
- end
-end
-
-if defined? $validate_xml_in_assert_success and $validate_xml_in_assert_success == true
- module Test
- module Unit
- module Assertions
- unless method_defined? :__assert_success_before_ovverride_by_instiki
- alias :__assert_success_before_ovverride_by_instiki :assert_success
- end
- def assert_success
- __assert_success_before_ovverride_by_instiki
- if @response.body.kind_of?(Proc) then # it's a file download, not an HTML content
- else assert_nothing_raised(@response.body) { REXML::Document.new(@response.body) } end
- end
- end
- end
- end
-end
diff --git a/test-old/unit/page_test.rb b/test-old/unit/page_test.rb
deleted file mode 100755
index 050bc8cd..00000000
--- a/test-old/unit/page_test.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/bin/env ruby -w
-
-require File.dirname(__FILE__) + '/../test_helper'
-require 'web'
-require 'page'
-
-class PageTest < Test::Unit::TestCase
-
- class MockWeb < Web
- def initialize() super(nil, 'test','test') end
- def [](wiki_word) %w( MyWay ThatWay SmartEngine ).include?(wiki_word) end
- def refresh_pages_with_references(name) end
- end
-
- def setup
- @page = Page.new(MockWeb.new, "FirstPage")
- @page.revise("HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\OverThere -- see SmartEngine in that SmartEngineGUI",
- Time.local(2004, 4, 4, 16, 50),
- "DavidHeinemeierHansson")
- end
-
- def test_lock
- assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
-
- @page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
-
- assert @page.locked?(Time.local(2004, 4, 4, 16, 50))
- assert !@page.locked?(Time.local(2004, 4, 4, 17, 1))
-
- @page.unlock
-
- assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
- end
-
- def test_lock_duration
- @page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
-
- assert_equal 15, @page.lock_duration(Time.local(2004, 4, 4, 16, 45))
- end
-
- def test_plain_name
- assert_equal "First Page", @page.plain_name
- end
-
- def test_revise
- @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
- assert_equal 2, @page.revisions.length, 'Should have two revisions'
- assert_equal 'MarianneSyhler', @page.author, 'Mary should be the author now'
- assert_equal 'DavidHeinemeierHansson', @page.revisions.first.author, 'David was the first author'
- end
-
- def test_revise_continous_revision
- @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
- assert_equal 2, @page.revisions.length
-
- @page.revise('HisWay would be MyWay in kinda update', Time.local(2004, 4, 4, 16, 57), 'MarianneSyhler')
- assert_equal 2, @page.revisions.length
- assert_equal 'HisWay would be MyWay in kinda update', @page.revisions.last.content
- assert_equal Time.local(2004, 4, 4, 16, 57), @page.revisions.last.created_at
-
- @page.revise('HisWay would be MyWay in the house', Time.local(2004, 4, 4, 16, 58), 'DavidHeinemeierHansson')
- assert_equal 3, @page.revisions.length
- assert_equal 'HisWay would be MyWay in the house', @page.revisions.last.content
-
- @page.revise('HisWay would be MyWay in my way', Time.local(2004, 4, 4, 17, 30), 'DavidHeinemeierHansson')
- assert_equal 4, @page.revisions.length
- end
-
- def test_revise_content_unchanged
- last_revision_before = @page.revisions.last
- revisions_number_before = @page.revisions.size
-
- assert_raises(Instiki::ValidationError) {
- @page.revise(@page.revisions.last.content.dup, Time.now, 'AlexeyVerkhovsky')
- }
-
- assert_same last_revision_before, @page.revisions.last
- assert_equal revisions_number_before, @page.revisions.size
- end
-
- def test_rollback
- @page.revise("spot two", Time.now, "David")
- @page.revise("spot three", Time.now + 2000, "David")
- assert_equal 3, @page.revisions.length, "Should have three revisions"
- @page.rollback(1, Time.now)
- assert_equal "spot two", @page.content
- end
-
-end
diff --git a/test-old/unit/revision_test.rb b/test-old/unit/revision_test.rb
deleted file mode 100755
index bd84e660..00000000
--- a/test-old/unit/revision_test.rb
+++ /dev/null
@@ -1,335 +0,0 @@
-#!/bin/env ruby -w
-
-require File.dirname(__FILE__) + '/../test_helper'
-require 'web'
-require 'revision'
-require 'fileutils'
-
-class RevisionTest < Test::Unit::TestCase
-
- def setup
- setup_test_wiki
- @web.markup = :textile
-
- @page = @wiki.read_page('wiki1', 'HomePage')
- ['MyWay', 'SmartEngine', 'ThatWay'].each do |page|
- @wiki.write_page('wiki1', page, page, Time.now, 'Me')
- end
- @wiki.write_page('wiki1','NoWikiWord', 'hey you', Time.now, 'Me')
-
- @revision = Revision.new(@page, 1,
- 'HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \OverThere -- ' +
- 'see SmartEngine in that SmartEngineGUI',
- Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
- end
-
- def test_wiki_words
- assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ), @revision.wiki_words.sort
-
- @wiki.write_page('wiki1', 'NoWikiWord', 'hey you', Time.now, 'Me')
- assert_equal [], @wiki.read_page('wiki1', 'NoWikiWord').wiki_words
- end
-
- def test_existing_pages
- assert_equal %w( MyWay SmartEngine ThatWay ), @revision.existing_pages.sort
- end
-
- def test_unexisting_pages
- assert_equal %w( HisWay SmartEngineGUI ), @revision.unexisting_pages.sort
- end
-
- def test_content_with_wiki_links
- assert_equal '
His Way? ' +
- 'would be My Way in kinda ' +
- 'That Way in ' +
- 'His Way? ' +
- 'though My Way OverThere—see ' +
- 'Smart Engine in that ' +
- 'Smart Engine GUI' +
- '?
',
- '("What is a wiki?":http://wiki.org/wiki.cgi?WhatIsWiki)')
- end
-
- def test_content_with_image_link
- assert_markup_parsed_as(
- '
This is a Textile image link.
',
- 'This !http://hobix.com/sample.jpg! is a Textile image link.')
- end
-
- def test_content_with_inlined_img_tag
- assert_markup_parsed_as(
- '
This is an inline image link.
',
- 'This is an inline image link.')
- assert_markup_parsed_as(
- '
This is an inline image link.
',
- 'This is an inline image link.')
- end
-
- def test_nowiki_tag
- assert_markup_parsed_as(
- '
Do not mark up [[this text]] or http://www.thislink.com.
',
- 'Do not mark up [[this text]] ' +
- 'or http://www.thislink.com.')
- end
-
- def test_multiline_nowiki_tag
- assert_markup_parsed_as(
- "
Do not mark \n up [[this text]] \nand http://this.url.com but markup " +
- 'this?
',
- "Do not mark \n up [[this text]] \n" +
- "and http://this.url.com but markup [[this]]")
- end
-
- def test_content_with_bracketted_wiki_word
- @web.brackets_only = true
- assert_markup_parsed_as(
- '
This is a WikiWord and a tricky name ' +
- 'Sperberg-McQueen?.
',
- 'This is a WikiWord and a tricky name [[Sperberg-McQueen]].')
- end
-
- def test_content_for_export
- assert_equal '
His Way would be ' +
- 'My Way in kinda ' +
- 'That Way in ' +
- 'His Way though ' +
- 'My Way OverThere—see ' +
- 'Smart Engine in that ' +
- 'Smart Engine GUI
',
- '[[With:Colon]]')
- end
-
- # TODO Remove the leading underscores from this test when upgrading to RedCloth 3.0.1;
- # also add a test for the "Unhappy Face" problem (another interesting RedCloth bug)
- def test_list_with_tildas
- list_with_tildas = <<-EOL
- * "a":~b
- * c~ d
- EOL
-
- assert_markup_parsed_as(
- "
',
- @web.pages['SecondPage'].display_content)
- end
-
- def test_pages_by_revision
- add_sample_pages
- assert_equal 'EverBeenHated', @web.select.by_revision.first.name
- end
-
- def test_pages_by_match
- add_sample_pages
- assert_equal 2, @web.select { |page| page.content =~ /me/i }.length
- assert_equal 1, @web.select { |page| page.content =~ /Who/i }.length
- assert_equal 0, @web.select { |page| page.content =~ /none/i }.length
- end
-
- def test_references
- add_sample_pages
- assert_equal 1, @web.select.pages_that_reference('EverBeenHated').length
- assert_equal 0, @web.select.pages_that_reference('EverBeenInLove').length
- end
-
- def test_delete
- add_sample_pages
- assert_equal 2, @web.pages.length
- @web.remove_pages([ @web.pages['EverBeenInLove'] ])
- assert_equal 1, @web.pages.length
- end
-
- def test_make_link
- add_sample_pages
-
- existing_page_wiki_url =
- 'Ever Been In Love'
- existing_page_published_url =
- 'Ever Been In Love'
- existing_page_static_url =
- 'Ever Been In Love'
- new_page_wiki_url =
- 'Unknown Word?'
- new_page_published_url =
- new_page_static_url =
- 'Unknown Word'
-
- # no options
- assert_equal existing_page_wiki_url, @web.make_link('EverBeenInLove')
-
- # :mode => :export
- assert_equal existing_page_static_url, @web.make_link('EverBeenInLove', nil, :mode => :export)
-
- # :mode => :publish
- assert_equal existing_page_published_url,
- @web.make_link('EverBeenInLove', nil, :mode => :publish)
-
- # new page, no options
- assert_equal new_page_wiki_url, @web.make_link('UnknownWord')
-
- # new page, :mode => :export
- assert_equal new_page_static_url, @web.make_link('UnknownWord', nil, :mode => :export)
-
- # new page, :mode => :publish
- assert_equal new_page_published_url, @web.make_link('UnknownWord', nil, :mode => :publish)
-
- # Escaping special characters in the name
- assert_equal(
- 'Smith & Wesson?',
- @web.make_link('Smith & Wesson'))
-
- # optionally using text as the link text
- assert_equal(
- existing_page_published_url.sub(/>Ever Been In Love, ">Haven't you ever been in love?<"),
- @web.make_link('EverBeenInLove', "Haven't you ever been in love?", :mode => :publish))
-
- end
-
- def test_initialize
- wiki_stub = Object.new
-
- web = Web.new(wiki_stub, 'Wiki2', 'wiki2', '123')
-
- assert_equal wiki_stub, web.wiki
- assert_equal 'Wiki2', web.name
- assert_equal 'wiki2', web.address
- assert_equal '123', web.password
-
- # new web should be set for maximum features enabled
- assert_equal :textile, web.markup
- assert_equal '008B26', web.color
- assert !web.safe_mode
- assert_equal({}, web.pages)
- assert web.allow_uploads
- assert_equal wiki_stub, web.wiki
- assert_nil web.additional_style
- assert !web.published
- assert !web.brackets_only
- assert !web.count_pages
- assert web.allow_uploads
- assert_equal 100, web.max_upload_size
- end
-
- def test_initialize_invalid_name
- wiki_stub = Object.new
- assert_raises(Instiki::ValidationError) {
- Web.new(wiki_stub, 'Wiki2', "wiki\234", '123')
- }
- end
-
- def test_new_page_linked_from_mother_page
- # this was a bug in revision 204
- home = @web.add_page('HomePage', 'This page refers to AnotherPage',
- Time.local(2004, 4, 4, 16, 50), 'Alexey Verkhovsky')
- @web.add_page('AnotherPage', 'This is \AnotherPage',
- Time.local(2004, 4, 4, 16, 51), 'Alexey Verkhovsky')
-
- assert_equal [home], @web.select.pages_that_link_to('AnotherPage')
- end
-
- def test_orphaned_pages
- add_sample_pages
- home = @web.add_page('HomePage',
- 'This is a home page, it should not be an orphan',
- Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
- author = @web.add_page('AlexeyVerkhovsky',
- 'This is an author page, it should not be an orphan',
- Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
- self_linked = @web.add_page('SelfLinked',
- 'I am me SelfLinked and link to EverBeenInLove',
- Time.local(2004, 4, 4, 16, 50), 'AnonymousCoward')
-
- # page that links to itself, and nobody else links to it must be an orphan
- assert_equal ['EverBeenHated', 'SelfLinked'],
- @web.select.orphaned_pages.collect{ |page| page.name }.sort
- end
-
-
- private
-
- def add_sample_pages
- @in_love = @web.add_page('EverBeenInLove', 'Who am I me',
- Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
- @hated = @web.add_page('EverBeenHated', 'I am me EverBeenHated',
- Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson')
- end
-end
diff --git a/test-old/unit/wiki_service_test.rb b/test-old/unit/wiki_service_test.rb
deleted file mode 100755
index c02c61ff..00000000
--- a/test-old/unit/wiki_service_test.rb
+++ /dev/null
@@ -1,129 +0,0 @@
-#!/bin/env ruby -w
-
-require File.dirname(__FILE__) + '/../test_helper'
-require 'wiki_service'
-require 'fileutils'
-
-class WikiServiceTest < Test::Unit::TestCase
-
- # Clean the test storage directory before the run
- unless defined? @@storage_cleaned
- FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/*.command_log'])
- FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/*.snapshot'])
- FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/*.tex'])
- FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/*.zip'])
- FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/*.pdf'])
- FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/instiki/*'])
- @@cleaned_storage = true
- WikiService.instance.setup('pswd', 'Wiki', 'wiki')
- end
-
- def setup
- @s = WikiService.instance
- @s.create_web 'Instiki', 'instiki'
- @web = @s.webs['instiki']
- end
-
- def teardown
- @s.delete_web 'instiki'
- end
-
- def test_read_write_page
- @s.write_page 'instiki', 'FirstPage', "Electric shocks, I love 'em",
- Time.now, 'DavidHeinemeierHansson'
- assert_equal "Electric shocks, I love 'em", @s.read_page('instiki', 'FirstPage').content
- end
-
- def test_read_only_operations
- @s.write_page 'instiki', 'TestReadOnlyOperations', 'Read only operations dont change the' +
- 'state of any object, and therefore should not be logged by Madeleine!',
- Time.now, 'AlexeyVerkhovsky'
-
- assert_doesnt_change_state_or_log :authenticate, 'pswd'
- assert_doesnt_change_state_or_log :read_page, 'instiki', 'TestReadOnlyOperations'
- assert_doesnt_change_state_or_log :setup?
- assert_doesnt_change_state_or_log :webs
-
- @s.write_page 'instiki', 'FirstPage', "Electric shocks, I love 'em",
- Time.now, 'DavidHeinemeierHansson'
- assert_equal "Electric shocks, I love 'em", @s.read_page('instiki', 'FirstPage').content
- end
-
- def test_aborted_transaction
- @s.write_page 'instiki', 'FirstPage', "Electric shocks, I love 'em",
- 10.minutes.ago, 'DavidHeinemeierHansson'
-
- assert_doesnt_change_state('revise_page with unchanged content') {
- begin
- @s.revise_page 'instiki', 'FirstPage', "Electric shocks, I love 'em",
- Time.now, 'DavidHeinemeierHansson'
- fail 'Expected Instiki::ValidationError not raised'
- rescue Instiki::ValidationError
- end
- }
- end
-
- def test_file_yard
- file_yard = @s.file_yard(@web)
- assert_equal FileYard, file_yard.class
- assert_equal(@s.storage_path + '/instiki', file_yard.files_path)
- end
-
- def test_edit_web_validations
- another_web = @s.create_web 'Another', 'another'
-
- # try to rename instiki web to another (which is the name of an already existing one)
- assert_raises(Instiki::ValidationError) {
- @s.edit_web('instiki', 'another', @web.name, @web.markup, @web.color, @web.additional_style)
- }
-
- assert_raises(Instiki::ValidationError) {
- @s.edit_web('nonexistant', 'another', @web.name, @web.markup, @web.color, @web.additional_style)
- }
- end
-
-
- # Checks that a method call or a block doesn;t change the persisted state of the wiki
- # Usage:
- # assert_doesnt_change_state :read_page, 'instiki', 'TestReadOnlyOperations'
- # or
- # assert_doesnt_change_state {|wiki| wiki.webs}
-
- def assert_doesnt_change_state(method, *args, &block)
- _assert_doesnt_change_state(including_command_log = false, method, *args, &block)
- end
-
- # Same as assert_doesnt_change_state, but also asserts that no vommand log is generated
- def assert_doesnt_change_state_or_log(method, *args, &block)
- _assert_doesnt_change_state(including_command_log = true, method, *args, &block)
- end
-
- private
-
- def _assert_doesnt_change_state(including_log, method, *args)
- WikiService.snapshot
- last_snapshot_before = last_snapshot
-
- if block_given?
- yield @s
- else
- @s.send(method, *args)
- end
-
- if including_log
- command_logs = Dir[RAILS_ROOT + 'storage/test/*.command_log']
- assert command_logs.empty?, "Calls to #{method} should not be logged"
- end
-
- last_snapshot_after = last_snapshot
- assert last_snapshot_before == last_snapshot_after,
- 'Calls to #{method} should not change the state of any persisted object'
- end
-
- def last_snapshot
- snapshots = Dir[RAILS_ROOT + '/storage/test/*.snapshot']
- assert !snapshots.empty?, "No snapshots found at #{RAILS_ROOT}/storage/test/"
- File.read(snapshots.last)
- end
-
-end
diff --git a/test-old/fixtures/rails.gif b/test/fixtures/rails.gif
similarity index 100%
rename from test-old/fixtures/rails.gif
rename to test/fixtures/rails.gif
diff --git a/test-old/functional/admin_controller_test.rb b/test/functional/admin_controller_test.rb
similarity index 100%
rename from test-old/functional/admin_controller_test.rb
rename to test/functional/admin_controller_test.rb
diff --git a/test-old/functional/application_test.rb b/test/functional/application_test.rb
similarity index 100%
rename from test-old/functional/application_test.rb
rename to test/functional/application_test.rb
diff --git a/test-old/functional/file_controller_test.rb b/test/functional/file_controller_test.rb
similarity index 100%
rename from test-old/functional/file_controller_test.rb
rename to test/functional/file_controller_test.rb
diff --git a/test/routes_test.rb b/test/functional/routes_test.rb
similarity index 100%
rename from test/routes_test.rb
rename to test/functional/routes_test.rb
diff --git a/test-old/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb
similarity index 100%
rename from test-old/functional/wiki_controller_test.rb
rename to test/functional/wiki_controller_test.rb
diff --git a/test-old/watir/e2e.rb b/test/watir/e2e.rb
similarity index 100%
rename from test-old/watir/e2e.rb
rename to test/watir/e2e.rb
From c4b7b2d9f23267406906e1f009d89fa06ac9efbe Mon Sep 17 00:00:00 2001
From: Rick Okin
Date: Tue, 9 Aug 2005 02:07:39 +0000
Subject: [PATCH 11/84] added chunks
---
lib/chunks/category.rb | 33 ++++++++
lib/chunks/chunk.rb | 86 +++++++++++++++++++
lib/chunks/engines.rb | 61 ++++++++++++++
lib/chunks/include.rb | 41 ++++++++++
lib/chunks/literal.rb | 31 +++++++
lib/chunks/nowiki.rb | 28 +++++++
lib/chunks/test.rb | 18 ++++
lib/chunks/uri.rb | 182 +++++++++++++++++++++++++++++++++++++++++
lib/chunks/wiki.rb | 141 +++++++++++++++++++++++++++++++
9 files changed, 621 insertions(+)
create mode 100644 lib/chunks/category.rb
create mode 100644 lib/chunks/chunk.rb
create mode 100644 lib/chunks/engines.rb
create mode 100644 lib/chunks/include.rb
create mode 100644 lib/chunks/literal.rb
create mode 100644 lib/chunks/nowiki.rb
create mode 100644 lib/chunks/test.rb
create mode 100644 lib/chunks/uri.rb
create mode 100644 lib/chunks/wiki.rb
diff --git a/lib/chunks/category.rb b/lib/chunks/category.rb
new file mode 100644
index 00000000..d08d8636
--- /dev/null
+++ b/lib/chunks/category.rb
@@ -0,0 +1,33 @@
+require 'chunks/chunk'
+
+# The category chunk looks for "category: news" on a line by
+# itself and parses the terms after the ':' as categories.
+# Other classes can search for Category chunks within
+# rendered content to find out what categories this page
+# should be in.
+#
+# Category lines can be hidden using ':category: news', for example
+class Category < Chunk::Abstract
+ CATEGORY_PATTERN = /^(:)?category\s*:(.*)$/i
+ def self.pattern() CATEGORY_PATTERN end
+
+ attr_reader :hidden, :list
+
+def initialize(match_data, content)
+ super(match_data, content)
+ @hidden = match_data[1]
+ @list = match_data[2].split(',').map { |c| c.strip }
+ @unmask_text = ''
+ if @hidden
+ @unmask_text = ''
+ else
+ category_urls = @list.map { |category| url(category) }.join(', ')
+ @unmask_text = '
category: ' + category_urls + '
'
+ end
+ end
+
+ # TODO move presentation of page metadata to controller/view
+ def url(category)
+ %{#{category}}
+ end
+end
diff --git a/lib/chunks/chunk.rb b/lib/chunks/chunk.rb
new file mode 100644
index 00000000..9ba3cc04
--- /dev/null
+++ b/lib/chunks/chunk.rb
@@ -0,0 +1,86 @@
+require 'uri/common'
+
+# A chunk is a pattern of text that can be protected
+# and interrogated by a renderer. Each Chunk class has a
+# +pattern+ that states what sort of text it matches.
+# Chunks are initalized by passing in the result of a
+# match by its pattern.
+
+module Chunk
+ class Abstract
+
+ # automatically construct the array of derivatives of Chunk::Abstract
+ @derivatives = []
+
+ class << self
+ attr_reader :derivatives
+ end
+
+ def self::inherited( klass )
+ Abstract::derivatives << klass
+ end
+
+ # the class name part of the mask strings
+ def self.mask_string
+ self.to_s.delete(':').downcase
+ end
+
+ # a regexp that matches all chunk_types masks
+ def Abstract::mask_re(chunk_types)
+ tmp = chunk_types.map{|klass| klass.mask_string}.join("|")
+ Regexp.new("chunk([0-9a-f]+n\\d+)(#{tmp})chunk")
+ end
+
+ attr_reader :text, :unmask_text, :unmask_mode
+
+ def initialize(match_data, content)
+ @text = match_data[0]
+ @content = content
+ @unmask_mode = :normal
+ end
+
+ # Find all the chunks of the given type in content
+ # Each time the pattern is matched, create a new
+ # chunk for it, and replace the occurance of the chunk
+ # in this content with its mask.
+ def self.apply_to(content)
+ content.gsub!( self.pattern ) do |match|
+ new_chunk = self.new($~, content)
+ content.add_chunk(new_chunk)
+ new_chunk.mask
+ end
+ end
+
+ # should contain only [a-z0-9]
+ def mask
+ @mask ||="chunk#{@id}#{self.class.mask_string}chunk"
+ end
+
+ # We should not use object_id because object_id is not guarantied
+ # to be unique when we restart the wiki (new object ids can equal old ones
+ # that were restored from madeleine storage)
+ def id
+ @id ||= "#{@content.page_id}n#{@content.chunk_id}"
+ end
+
+ def unmask
+ @content.sub!(mask, @unmask_text)
+ end
+
+ def rendered?
+ @unmask_mode == :normal
+ end
+
+ def escaped?
+ @unmask_mode == :escape
+ end
+
+ def revert
+ @content.sub!(mask, @text)
+ # unregister
+ @content.delete_chunk(self)
+ end
+
+ end
+
+end
diff --git a/lib/chunks/engines.rb b/lib/chunks/engines.rb
new file mode 100644
index 00000000..fe5a96a8
--- /dev/null
+++ b/lib/chunks/engines.rb
@@ -0,0 +1,61 @@
+$: << File.dirname(__FILE__) + "../../lib"
+
+require 'redcloth'
+require 'bluecloth_tweaked'
+require 'rdocsupport'
+require 'chunks/chunk'
+
+# The markup engines are Chunks that call the one of RedCloth
+# or RDoc to convert text. This markup occurs when the chunk is required
+# to mask itself.
+module Engines
+ class AbstractEngine < Chunk::Abstract
+
+ # Create a new chunk for the whole content and replace it with its mask.
+ def self.apply_to(content)
+ new_chunk = self.new(content)
+ content.replace(new_chunk.mask)
+ end
+
+ private
+
+ # Never create engines by constructor - use apply_to instead
+ def initialize(content)
+ @content = content
+ end
+
+ end
+
+ class Textile < AbstractEngine
+ def mask
+ redcloth = RedCloth.new(@content, [:hard_breaks] + @content.options[:engine_opts])
+ redcloth.filter_html = false
+ redcloth.no_span_caps = false
+ redcloth.to_html(:textile)
+ end
+ end
+
+ class Markdown < AbstractEngine
+ def mask
+ BlueCloth.new(@content, @content.options[:engine_opts]).to_html
+ end
+ end
+
+ class Mixed < AbstractEngine
+ def mask
+ redcloth = RedCloth.new(@content, @content.options[:engine_opts])
+ redcloth.filter_html = false
+ redcloth.no_span_caps = false
+ redcloth.to_html
+ end
+ end
+
+ class RDoc < AbstractEngine
+ def mask
+ RDocSupport::RDocFormatter.new(@content).to_html
+ end
+ end
+
+ MAP = { :textile => Textile, :markdown => Markdown, :mixed => Mixed, :rdoc => RDoc }
+ MAP.default = Textile
+end
diff --git a/lib/chunks/include.rb b/lib/chunks/include.rb
new file mode 100644
index 00000000..370093cc
--- /dev/null
+++ b/lib/chunks/include.rb
@@ -0,0 +1,41 @@
+require 'chunks/wiki'
+
+# Includes the contents of another page for rendering.
+# The include command looks like this: "[[!include PageName]]".
+# It is a WikiReference since it refers to another page (PageName)
+# and the wiki content using this command must be notified
+# of changes to that page.
+# If the included page could not be found, a warning is displayed.
+
+class Include < WikiChunk::WikiReference
+
+ INCLUDE_PATTERN = /\[\[!include\s+(.*?)\]\]\s*/i
+ def self.pattern() INCLUDE_PATTERN end
+
+
+ def initialize(match_data, content)
+ super
+ @page_name = match_data[1].strip
+ @unmask_text = get_unmask_text_avoiding_recursion_loops
+ end
+
+ private
+
+ def get_unmask_text_avoiding_recursion_loops
+ if refpage then
+ refpage.clear_display_cache
+ if refpage.wiki_includes.include?(@content.page_name)
+ # this will break the recursion
+ @content.delete_chunk(self)
+ return "Recursive include detected; #{@page_name} --> #{@content.page_name} " +
+ "--> #{@page_name}\n"
+ else
+ @content.merge_chunks(refpage.display_content)
+ return refpage.display_content.pre_rendered
+ end
+ else
+ return "Could not include #{@page_name}\n"
+ end
+ end
+
+end
diff --git a/lib/chunks/literal.rb b/lib/chunks/literal.rb
new file mode 100644
index 00000000..09da4005
--- /dev/null
+++ b/lib/chunks/literal.rb
@@ -0,0 +1,31 @@
+require 'chunks/chunk'
+
+# These are basic chunks that have a pattern and can be protected.
+# They are used by rendering process to prevent wiki rendering
+# occuring within literal areas such as and
blocks
+# and within HTML tags.
+module Literal
+
+ class AbstractLiteral < Chunk::Abstract
+
+ def initialize(match_data, content)
+ super
+ @unmask_text = @text
+ end
+
+ end
+
+ # A literal chunk that protects 'code' and 'pre' tags from wiki rendering.
+ class Pre < AbstractLiteral
+ PRE_BLOCKS = "a|pre|code"
+ PRE_PATTERN = Regexp.new('<('+PRE_BLOCKS+')\b[^>]*?>.*?\1>', Regexp::MULTILINE)
+ def self.pattern() PRE_PATTERN end
+ end
+
+ # A literal chunk that protects HTML tags from wiki rendering.
+ class Tags < AbstractLiteral
+ TAGS = "a|img|em|strong|div|span|table|td|th|ul|ol|li|dl|dt|dd"
+ TAGS_PATTERN = Regexp.new('<(?:'+TAGS+')[^>]*?>', Regexp::MULTILINE)
+ def self.pattern() TAGS_PATTERN end
+ end
+end
diff --git a/lib/chunks/nowiki.rb b/lib/chunks/nowiki.rb
new file mode 100644
index 00000000..ef99ec0b
--- /dev/null
+++ b/lib/chunks/nowiki.rb
@@ -0,0 +1,28 @@
+require 'chunks/chunk'
+
+# This chunks allows certain parts of a wiki page to be hidden from the
+# rest of the rendering pipeline. It should be run at the beginning
+# of the pipeline in `wiki_content.rb`.
+#
+# An example use of this chunk is to markup double brackets or
+# auto URI links:
+# Here are [[double brackets]] and a URI: www.uri.org
+#
+# The contents of the chunks will not be processed by any other chunk
+# so the `www.uri.org` and the double brackets will appear verbatim.
+#
+# Author: Mark Reid
+# Created: 8th June 2004
+class NoWiki < Chunk::Abstract
+
+ NOWIKI_PATTERN = Regexp.new('(.*?)', Regexp::MULTILINE)
+ def self.pattern() NOWIKI_PATTERN end
+
+ attr_reader :plain_text
+
+ def initialize(match_data, content)
+ super
+ @plain_text = @unmask_text = match_data[1]
+ end
+
+end
diff --git a/lib/chunks/test.rb b/lib/chunks/test.rb
new file mode 100644
index 00000000..edf77d14
--- /dev/null
+++ b/lib/chunks/test.rb
@@ -0,0 +1,18 @@
+require 'test/unit'
+
+class ChunkTest < Test::Unit::TestCase
+
+ # Asserts a number of tests for the given type and text.
+ def match(type, test_text, expected)
+ pattern = type.pattern
+ assert_match(pattern, test_text)
+ pattern =~ test_text # Previous assertion guarantees match
+ chunk = type.new($~)
+
+ # Test if requested parts are correct.
+ for method_sym, value in expected do
+ assert_respond_to(chunk, method_sym)
+ assert_equal(value, chunk.method(method_sym).call, "Checking value of '#{method_sym}'")
+ end
+ end
+end
diff --git a/lib/chunks/uri.rb b/lib/chunks/uri.rb
new file mode 100644
index 00000000..1a208535
--- /dev/null
+++ b/lib/chunks/uri.rb
@@ -0,0 +1,182 @@
+require 'chunks/chunk'
+
+# This wiki chunk matches arbitrary URIs, using patterns from the Ruby URI modules.
+# It parses out a variety of fields that could be used by renderers to format
+# the links in various ways (shortening domain names, hiding email addresses)
+# It matches email addresses and host.com.au domains without schemes (http://)
+# but adds these on as required.
+#
+# The heuristic used to match a URI is designed to err on the side of caution.
+# That is, it is more likely to not autolink a URI than it is to accidently
+# autolink something that is not a URI. The reason behind this is it is easier
+# to force a URI link by prefixing 'http://' to it than it is to escape and
+# incorrectly marked up non-URI.
+#
+# I'm using a part of the [ISO 3166-1 Standard][iso3166] for country name suffixes.
+# The generic names are from www.bnoack.com/data/countrycode2.html)
+# [iso3166]: http://geotags.com/iso3166/
+
+class URIChunk < Chunk::Abstract
+ include URI::REGEXP::PATTERN
+
+ # this condition is to get rid of pesky warnings in tests
+ unless defined? URIChunk::INTERNET_URI_REGEXP
+
+ GENERIC = 'aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org'
+
+ COUNTRY = 'ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|' +
+ 'bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cf|cd|cg|ch|ci|ck|cl|' +
+ 'cm|cn|co|cr|cs|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|fi|' +
+ 'fj|fk|fm|fo|fr|fx|ga|gb|gd|ge|gf|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|' +
+ 'hk|hm|hn|hr|ht|hu|id|ie|il|in|io|iq|ir|is|it|jm|jo|jp|ke|kg|kh|ki|km|kn|' +
+ 'kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|' +
+ 'mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nt|' +
+ 'nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|' +
+ 'sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|' +
+ 'tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|' +
+ 'ws|ye|yt|yu|za|zm|zr|zw'
+ # These are needed otherwise HOST will match almost anything
+ TLDS = "(?:#{GENERIC}|#{COUNTRY})"
+
+ # Redefine USERINFO so that it must have non-zero length
+ USERINFO = "(?:[#{UNRESERVED};:&=+$,]|#{ESCAPED})+"
+
+ # unreserved_no_ending = alphanum | mark, but URI_ENDING [)!] excluded
+ UNRESERVED_NO_ENDING = "-_.~*'(#{ALNUM}"
+
+ # this ensures that query or fragment do not end with URI_ENDING
+ # and enable us to use a much simpler self.pattern Regexp
+
+ # uric_no_ending = reserved | unreserved_no_ending | escaped
+ URIC_NO_ENDING = "(?:[#{UNRESERVED_NO_ENDING}#{RESERVED}]|#{ESCAPED})"
+ # query = *uric
+ QUERY = "#{URIC_NO_ENDING}*"
+ # fragment = *uric
+ FRAGMENT = "#{URIC_NO_ENDING}*"
+
+ # DOMLABEL is defined in the ruby uri library, TLDS is defined above
+ INTERNET_HOSTNAME = "(?:#{DOMLABEL}\\.)+#{TLDS}"
+
+ # Correct a typo bug in ruby 1.8.x lib/uri/common.rb
+ PORT = '\\d*'
+
+ INTERNET_URI =
+ "(?:(#{SCHEME}):/{0,2})?" + # Optional scheme: (\1)
+ "(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2)
+ "(#{INTERNET_HOSTNAME})" + # Mandatory hostname (\3)
+ "(?::(#{PORT}))?" + # Optional :port (\4)
+ "(#{ABS_PATH})?" + # Optional absolute path (\5)
+ "(?:\\?(#{QUERY}))?" + # Optional ?query (\6)
+ "(?:\\#(#{FRAGMENT}))?" + # Optional #fragment (\7)
+ '(?=\.?(?:\s|\)|\z))' # ends only with optional dot + space or ")"
+ # or end of the string
+
+ SUSPICIOUS_PRECEDING_CHARACTER = '(!|\"\:|\"|\\\'|\]\()?' # any of !, ":, ", ', ](
+
+ INTERNET_URI_REGEXP =
+ Regexp.new(SUSPICIOUS_PRECEDING_CHARACTER + INTERNET_URI, Regexp::EXTENDED, 'N')
+
+ end
+
+ def URIChunk.pattern
+ INTERNET_URI_REGEXP
+ end
+
+ attr_reader :user, :host, :port, :path, :query, :fragment, :link_text
+
+ def self.apply_to(content)
+ content.gsub!( self.pattern ) do |matched_text|
+ chunk = self.new($~, content)
+ if chunk.avoid_autolinking?
+ # do not substitute nor register the chunk
+ matched_text
+ else
+ content.add_chunk(chunk)
+ chunk.mask
+ end
+ end
+ end
+
+ def initialize(match_data, content)
+ super
+ @link_text = match_data[0]
+ @suspicious_preceding_character = match_data[1]
+ @original_scheme, @user, @host, @port, @path, @query, @fragment = match_data[2..-1]
+ treat_trailing_character
+ @unmask_text = "#{link_text}"
+ end
+
+ def avoid_autolinking?
+ not @suspicious_preceding_character.nil?
+ end
+
+ def treat_trailing_character
+ # If the last character matched by URI pattern is in ! or ), this may be part of the markup,
+ # not a URL. We should handle it as such. It is possible to do it by a regexp, but
+ # much easier to do programmatically
+ last_char = @link_text[-1..-1]
+ if last_char == ')' or last_char == '!'
+ @trailing_punctuation = last_char
+ @link_text.chop!
+ [@original_scheme, @user, @host, @port, @path, @query, @fragment].compact.last.chop!
+ else
+ @trailing_punctuation = nil
+ end
+ end
+
+ def scheme
+ @original_scheme or (@user ? 'mailto' : 'http')
+ end
+
+ def scheme_delimiter
+ scheme == 'mailto' ? ':' : '://'
+ end
+
+ def user_delimiter
+ '@' unless @user.nil?
+ end
+
+ def port_delimiter
+ ':' unless @port.nil?
+ end
+
+ def query_delimiter
+ '?' unless @query.nil?
+ end
+
+ def uri
+ [scheme, scheme_delimiter, user, user_delimiter, host, port_delimiter, port, path,
+ query_delimiter, query].compact.join
+ end
+
+end
+
+# uri with mandatory scheme but less restrictive hostname, like
+# http://localhost:2500/blah.html
+class LocalURIChunk < URIChunk
+
+ unless defined? LocalURIChunk::LOCAL_URI_REGEXP
+ # hostname can be just a simple word like 'localhost'
+ ANY_HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?"
+
+ # The basic URI expression as a string
+ # Scheme and hostname are mandatory
+ LOCAL_URI =
+ "(?:(#{SCHEME})://)+" + # Mandatory scheme:// (\1)
+ "(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2)
+ "(#{ANY_HOSTNAME})" + # Mandatory hostname (\3)
+ "(?::(#{PORT}))?" + # Optional :port (\4)
+ "(#{ABS_PATH})?" + # Optional absolute path (\5)
+ "(?:\\?(#{QUERY}))?" + # Optional ?query (\6)
+ "(?:\\#(#{FRAGMENT}))?" + # Optional #fragment (\7)
+ '(?=\.?(?:\s|\)|\z))' # ends only with optional dot + space or ")"
+ # or end of the string
+
+ LOCAL_URI_REGEXP = Regexp.new(SUSPICIOUS_PRECEDING_CHARACTER + LOCAL_URI, Regexp::EXTENDED, 'N')
+ end
+
+ def LocalURIChunk.pattern
+ LOCAL_URI_REGEXP
+ end
+
+end
diff --git a/lib/chunks/wiki.rb b/lib/chunks/wiki.rb
new file mode 100644
index 00000000..840f644a
--- /dev/null
+++ b/lib/chunks/wiki.rb
@@ -0,0 +1,141 @@
+require 'wiki_words'
+require 'chunks/chunk'
+require 'chunks/wiki'
+require 'cgi'
+
+# Contains all the methods for finding and replacing wiki related links.
+module WikiChunk
+ include Chunk
+
+ # A wiki reference is the top-level class for anything that refers to
+ # another wiki page.
+ class WikiReference < Chunk::Abstract
+
+ # Name of the referenced page
+ attr_reader :page_name
+
+ # the referenced page
+ def refpage
+ @content.web.pages[@page_name]
+ end
+
+ end
+
+ # A wiki link is the top-level class for links that refers to
+ # another wiki page.
+ class WikiLink < WikiReference
+
+ attr_reader :link_text, :link_type
+
+ def initialize(match_data, content)
+ super
+ @link_type = :show
+ end
+
+ def self.apply_to(content)
+ content.gsub!( self.pattern ) do |matched_text|
+ chunk = self.new($~, content)
+ if chunk.textile_url?
+ # do not substitute
+ matched_text
+ else
+ content.add_chunk(chunk)
+ chunk.mask
+ end
+ end
+ end
+
+ # the referenced page
+ def refpage
+ @content.web.pages[@page_name]
+ end
+
+ def textile_url?
+ not @textile_link_suffix.nil?
+ end
+
+ end
+
+ # This chunk matches a WikiWord. WikiWords can be escaped
+ # by prepending a '\'. When this is the case, the +escaped_text+
+ # method will return the WikiWord instead of the usual +nil+.
+ # The +page_name+ method returns the matched WikiWord.
+ class Word < WikiLink
+
+ attr_reader :escaped_text
+
+ unless defined? WIKI_WORD
+ WIKI_WORD = Regexp.new('(":)?(\\\\)?(' + WikiWords::WIKI_WORD_PATTERN + ')\b', 0, "utf-8")
+ end
+
+ def self.pattern
+ WIKI_WORD
+ end
+
+ def initialize(match_data, content)
+ super
+ @textile_link_suffix, @escape, @page_name = match_data[1..3]
+ if @escape
+ @unmask_mode = :escape
+ @escaped_text = @page_name
+ else
+ @escaped_text = nil
+ end
+ @link_text = WikiWords.separate(@page_name)
+ @unmask_text = (@escaped_text || @content.page_link(@page_name, @link_text, @link_type))
+ end
+
+ end
+
+ # This chunk handles [[bracketted wiki words]] and
+ # [[AliasedWords|aliased wiki words]]. The first part of an
+ # aliased wiki word must be a WikiWord. If the WikiWord
+ # is aliased, the +link_text+ field will contain the
+ # alias, otherwise +link_text+ will contain the entire
+ # contents within the double brackets.
+ #
+ # NOTE: This chunk must be tested before WikiWord since
+ # a WikiWords can be a substring of a WikiLink.
+ class Link < WikiLink
+
+ unless defined? WIKI_LINK
+ WIKI_LINK = /(":)?\[\[\s*([^\]\s][^\]]+?)\s*\]\]/
+ LINK_TYPE_SEPARATION = Regexp.new('^(.+):((file)|(pic))$', 0, 'utf-8')
+ ALIAS_SEPARATION = Regexp.new('^(.+)\|(.+)$', 0, 'utf-8')
+ end
+
+ def self.pattern() WIKI_LINK end
+
+ def initialize(match_data, content)
+ super
+ @textile_link_suffix, @page_name = match_data[1..2]
+ @link_text = @page_name
+ separate_link_type
+ separate_alias
+ @unmask_text = @content.page_link(@page_name, @link_text, @link_type)
+ end
+
+ private
+
+ # if link wihin the brackets has a form of [[filename:file]] or [[filename:pic]],
+ # this means a link to a picture or a file
+ def separate_link_type
+ link_type_match = LINK_TYPE_SEPARATION.match(@page_name)
+ if link_type_match
+ @link_text = @page_name = link_type_match[1]
+ @link_type = link_type_match[2..3].compact[0].to_sym
+ end
+ end
+
+ # link text may be different from page name. this will look like [[actual page|link text]]
+ def separate_alias
+ alias_match = ALIAS_SEPARATION.match(@page_name)
+ if alias_match
+ @page_name, @link_text = alias_match[1..2]
+ end
+ # note that [[filename|link text:file]] is also supported
+ end
+
+ end
+
+end
From 26c046cdfa1d62151c4fe271590b37f97037ec0a Mon Sep 17 00:00:00 2001
From: Rick Okin
Date: Tue, 9 Aug 2005 02:20:28 +0000
Subject: [PATCH 12/84] move to AR
---
Rakefile | 202 +++++++++++++++
app/controllers/admin_controller.rb | 2 +-
app/controllers/application.rb | 6 +-
app/controllers/file_controller.rb | 2 +-
app/controllers/wiki_controller.rb | 7 +-
app/models/page.rb | 125 ++++++++-
app/models/revision.rb | 121 ++++++++-
app/models/system.rb | 4 +
app/models/web.rb | 174 ++++++++++++-
app/views/wiki/list.rhtml | 2 +-
app/views/wiki/page.rhtml | 2 +-
config/database.yml | 81 ++++--
config/environment.rb | 2 +
config/environments/development.rb | 1 -
config/environments/test.rb | 13 +-
db/development_structure.sql | 40 +++
db/pages.erbsql | 7 +-
db/revisions.erbsql | 15 +-
db/schema.postgre.sql | 43 ++++
db/system.erbsql | 4 +
db/webs.erbsql | 14 +-
lib/author.rb | 18 ++
lib/chunks/test.rb | 2 +-
lib/db_structure.rb | 14 +
lib/file_yard.rb | 59 +++++
lib/page_set.rb | 89 +++++++
lib/wiki.rb | 96 +++++++
lib/wiki_content.rb | 206 +++++++++++++++
lib/wiki_words.rb | 23 ++
rakefile.rb | 134 ----------
script/console | 23 ++
script/create_db | 2 +-
script/server | 100 ++------
test/fixtures/pages.yml | 56 +++-
test/fixtures/revisions.yml | 84 +++++-
test/fixtures/system.yml | 2 +
test/fixtures/webs.yml | 13 +-
test/functional/admin_controller_test.rb | 113 ++++----
test/functional/application_test.rb | 23 +-
test/functional/file_controller_test.rb | 39 +--
test/functional/routes_test.rb | 2 +-
test/functional/wiki_controller_test.rb | 242 ++++++++----------
test/test_helper.rb | 90 ++++++-
test/unit/diff_test.rb | 4 +-
test/unit/file_yard_test.rb | 4 +-
test/unit/page_test.rb | 77 +++++-
test/unit/redcloth_for_tex_test.rb | 4 +-
test/unit/revision_test.rb | 312 ++++++++++++++++++++++-
test/unit/uri_test.rb | 2 +-
test/unit/web_test.rb | 157 +++++++++++-
test/unit/wiki_words_test.rb | 4 +-
51 files changed, 2345 insertions(+), 516 deletions(-)
create mode 100644 Rakefile
create mode 100644 app/models/system.rb
create mode 100644 db/development_structure.sql
create mode 100644 db/schema.postgre.sql
create mode 100644 db/system.erbsql
create mode 100644 lib/author.rb
create mode 100644 lib/file_yard.rb
create mode 100644 lib/page_set.rb
create mode 100644 lib/wiki.rb
create mode 100644 lib/wiki_content.rb
create mode 100644 lib/wiki_words.rb
create mode 100644 script/console
create mode 100644 test/fixtures/system.yml
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 00000000..5407e140
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,202 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+$VERBOSE = nil
+TEST_CHANGES_SINCE = Time.now - 600
+
+desc "Run all the tests on a fresh test database"
+task :default => [ :test_units, :test_functional ]
+
+
+desc 'Require application environment.'
+task :environment do
+ unless defined? RAILS_ROOT
+ require File.dirname(__FILE__) + '/config/environment'
+ end
+end
+
+desc "Generate API documentation, show coding stats"
+task :doc => [ :appdoc, :stats ]
+
+
+# Look up tests for recently modified sources.
+def recent_tests(source_pattern, test_path, touched_since = 10.minutes.ago)
+ FileList[source_pattern].map do |path|
+ if File.mtime(path) > touched_since
+ test = "#{test_path}/#{File.basename(path, '.rb')}_test.rb"
+ test if File.exists?(test)
+ end
+ end.compact
+end
+
+desc 'Test recent changes.'
+Rake::TestTask.new(:recent => [ :clone_structure_to_test ]) do |t|
+ since = TEST_CHANGES_SINCE
+ touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } +
+ recent_tests('app/models/*.rb', 'test/unit', since) +
+ recent_tests('app/controllers/*.rb', 'test/functional', since)
+
+ t.libs << 'test'
+ t.verbose = true
+ t.test_files = touched.uniq
+end
+task :test_recent => [ :clone_structure_to_test ]
+
+desc "Run the unit tests in test/unit"
+Rake::TestTask.new("test_units") { |t|
+ t.libs << "test"
+ t.pattern = 'test/unit/**/*_test.rb'
+ t.verbose = true
+}
+task :test_units => [ :clone_structure_to_test ]
+
+desc "Run the functional tests in test/functional"
+Rake::TestTask.new("test_functional") { |t|
+ t.libs << "test"
+ t.pattern = 'test/functional/**/*_test.rb'
+ t.verbose = true
+}
+task :test_functional => [ :clone_structure_to_test ]
+
+desc "Generate documentation for the application"
+Rake::RDocTask.new("appdoc") { |rdoc|
+ rdoc.rdoc_dir = 'doc/app'
+ rdoc.title = "Rails Application Documentation"
+ rdoc.options << '--line-numbers --inline-source'
+ rdoc.rdoc_files.include('doc/README_FOR_APP')
+ rdoc.rdoc_files.include('app/**/*.rb')
+}
+
+desc "Generate documentation for the Rails framework"
+Rake::RDocTask.new("apidoc") { |rdoc|
+ rdoc.rdoc_dir = 'doc/api'
+ rdoc.template = "#{ENV['template']}.rb" if ENV['template']
+ rdoc.title = "Rails Framework Documentation"
+ rdoc.options << '--line-numbers --inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('CHANGELOG')
+ rdoc.rdoc_files.include('vendor/rails/railties/CHANGELOG')
+ rdoc.rdoc_files.include('vendor/rails/railties/MIT-LICENSE')
+ rdoc.rdoc_files.include('vendor/rails/activerecord/README')
+ rdoc.rdoc_files.include('vendor/rails/activerecord/CHANGELOG')
+ rdoc.rdoc_files.include('vendor/rails/activerecord/lib/active_record/**/*.rb')
+ rdoc.rdoc_files.exclude('vendor/rails/activerecord/lib/active_record/vendor/*')
+ rdoc.rdoc_files.include('vendor/rails/actionpack/README')
+ rdoc.rdoc_files.include('vendor/rails/actionpack/CHANGELOG')
+ rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_controller/**/*.rb')
+ rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_view/**/*.rb')
+ rdoc.rdoc_files.include('vendor/rails/actionmailer/README')
+ rdoc.rdoc_files.include('vendor/rails/actionmailer/CHANGELOG')
+ rdoc.rdoc_files.include('vendor/rails/actionmailer/lib/action_mailer/base.rb')
+ rdoc.rdoc_files.include('vendor/rails/actionwebservice/README')
+ rdoc.rdoc_files.include('vendor/rails/actionwebservice/CHANGELOG')
+ rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service.rb')
+ rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/*.rb')
+ rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/api/*.rb')
+ rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/client/*.rb')
+ rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/container/*.rb')
+ rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/dispatcher/*.rb')
+ rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/protocol/*.rb')
+ rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/support/*.rb')
+ rdoc.rdoc_files.include('vendor/rails/activesupport/README')
+ rdoc.rdoc_files.include('vendor/rails/activesupport/CHANGELOG')
+ rdoc.rdoc_files.include('vendor/rails/activesupport/lib/active_support/**/*.rb')
+}
+
+desc "Report code statistics (KLOCs, etc) from the application"
+task :stats => [ :environment ] do
+ require 'code_statistics'
+ CodeStatistics.new(
+ ["Helpers", "app/helpers"],
+ ["Controllers", "app/controllers"],
+ ["APIs", "app/apis"],
+ ["Components", "components"],
+ ["Functionals", "test/functional"],
+ ["Models", "app/models"],
+ ["Units", "test/unit"]
+ ).to_s
+end
+
+desc "Recreate the test databases from the development structure"
+task :clone_structure_to_test => [ :db_structure_dump, :purge_test_database ] do
+ abcs = ActiveRecord::Base.configurations
+ case abcs["test"]["adapter"]
+ when "mysql"
+ ActiveRecord::Base.establish_connection(:test)
+ ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
+ IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table|
+ ActiveRecord::Base.connection.execute(table)
+ end
+ when "postgresql"
+ ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
+ ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
+ ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
+ `psql -U "#{abcs["test"]["username"]}" -f db/#{RAILS_ENV}_structure.sql #{abcs["test"]["database"]}`
+ when "sqlite", "sqlite3"
+ `#{abcs[RAILS_ENV]["adapter"]} #{abcs["test"]["dbfile"]} < db/#{RAILS_ENV}_structure.sql`
+ when "sqlserver"
+ `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
+ else
+ raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
+ end
+end
+
+desc "Dump the database structure to a SQL file"
+task :db_structure_dump => :environment do
+ abcs = ActiveRecord::Base.configurations
+ case abcs[RAILS_ENV]["adapter"]
+ when "mysql"
+ ActiveRecord::Base.establish_connection(abcs[RAILS_ENV])
+ File.open("db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
+ when "postgresql"
+ ENV['PGHOST'] = abcs[RAILS_ENV]["host"] if abcs[RAILS_ENV]["host"]
+ ENV['PGPORT'] = abcs[RAILS_ENV]["port"].to_s if abcs[RAILS_ENV]["port"]
+ ENV['PGPASSWORD'] = abcs[RAILS_ENV]["password"].to_s if abcs[RAILS_ENV]["password"]
+ `pg_dump -U "#{abcs[RAILS_ENV]["username"]}" -s -x -O -f db/#{RAILS_ENV}_structure.sql #{abcs[RAILS_ENV]["database"]}`
+ when "sqlite", "sqlite3"
+ `#{abcs[RAILS_ENV]["adapter"]} #{abcs[RAILS_ENV]["dbfile"]} .schema > db/#{RAILS_ENV}_structure.sql`
+ when "sqlserver"
+ `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /f db\\#{RAILS_ENV}_structure.sql /q /A /r`
+ `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /F db\ /q /A /r`
+ else
+ raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
+ end
+end
+
+desc "Empty the test database"
+task :purge_test_database => :environment do
+ abcs = ActiveRecord::Base.configurations
+ case abcs["test"]["adapter"]
+ when "mysql"
+ ActiveRecord::Base.establish_connection(:test)
+ ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"])
+ when "postgresql"
+ ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
+ ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
+ ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
+ `dropdb -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
+ `createdb -T template0 -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
+ when "sqlite","sqlite3"
+ File.delete(abcs["test"]["dbfile"]) if File.exist?(abcs["test"]["dbfile"])
+ when "sqlserver"
+ dropfkscript = "#{abcs["test"]["host"]}.#{abcs["test"]["database"]}.DP1".gsub(/\\/,'-')
+ `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{dropfkscript}`
+ `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
+ else
+ raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
+ end
+end
+
+desc "Clears all *.log files in log/"
+task :clear_logs => :environment do
+ FileList["log/*.log"].each do |log_file|
+ f = File.open(log_file, "w")
+ f.close
+ end
+end
+
+desc "Migrate the database according to the migrate scripts in db/migrate (only supported on PG/MySQL). A specific version can be targetted with VERSION=x"
+task :migrate => :environment do
+ ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/db/migrate/', ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
+end
\ No newline at end of file
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb
index 6bca0f15..a52b2005 100644
--- a/app/controllers/admin_controller.rb
+++ b/app/controllers/admin_controller.rb
@@ -46,7 +46,6 @@ class AdminController < ApplicationController
end
def edit_web
-
system_password = @params['system_password']
if system_password
# form submitted
@@ -67,6 +66,7 @@ class AdminController < ApplicationController
flash[:info] = "Web '#{@params['address']}' was successfully updated"
redirect_home(@params['address'])
rescue Instiki::ValidationError => e
+ logger.warn e.message
@error = e.message
# and re-render the same template again
end
diff --git a/app/controllers/application.rb b/app/controllers/application.rb
index 1e2af4e6..7f608e49 100644
--- a/app/controllers/application.rb
+++ b/app/controllers/application.rb
@@ -10,12 +10,12 @@ class ApplicationController < ActionController::Base
# a global variable is used here because Rails reloads controller and model classes in the
# development environment; therefore, storing it as a class variable does not work
# class variable is, anyway, not much different from a global variable
- $instiki_wiki_service = the_wiki
+ #$instiki_wiki_service = the_wiki
logger.debug("Wiki service: #{the_wiki.to_s}")
end
def self.wiki
- $instiki_wiki_service
+ Wiki.new
end
protected
@@ -146,7 +146,7 @@ class ApplicationController < ActionController::Base
end
def wiki
- $instiki_wiki_service
+ self.class.wiki
end
def needs_authorization?(action)
diff --git a/app/controllers/file_controller.rb b/app/controllers/file_controller.rb
index bf0ee964..e67ee3a2 100644
--- a/app/controllers/file_controller.rb
+++ b/app/controllers/file_controller.rb
@@ -78,7 +78,7 @@ class FileController < ApplicationController
return false
end
- unless @web.allow_uploads
+ unless @web.allow_uploads?
render_text 'File uploads are blocked by the webmaster', '403 Forbidden'
return false
end
diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb
index 43d55b2e..c274e209 100644
--- a/app/controllers/wiki_controller.rb
+++ b/app/controllers/wiki_controller.rb
@@ -1,4 +1,3 @@
-require 'application'
require 'fileutils'
require 'redcloth_for_tex'
require 'parsedate'
@@ -156,7 +155,7 @@ class WikiController < ApplicationController
end
def published
- if @web.published
+ if @web.published?
@page = wiki.read_page(@web_name, @page_name || 'HomePage')
else
redirect_home
@@ -270,7 +269,7 @@ class WikiController < ApplicationController
end
def export_web_to_tex(file_path)
- @tex_content = table_of_contents(@web.pages['HomePage'].content, render_tex_web)
+ @tex_content = table_of_contents(@web.page('HomePage').content, render_tex_web)
File.open(file_path, 'w') { |f| f.write(render_to_string('wiki/tex_web')) }
end
@@ -342,7 +341,7 @@ class WikiController < ApplicationController
end
def rss_with_content_allowed?
- @web.password.nil? or @web.published
+ @web.password.nil? or @web.published?
end
def truncate(text, length = 30, truncate_string = '...')
diff --git a/app/models/page.rb b/app/models/page.rb
index 5f85c8ab..6baa5802 100644
--- a/app/models/page.rb
+++ b/app/models/page.rb
@@ -1,4 +1,125 @@
class Page < ActiveRecord::Base
belongs_to :web
- has_many :pages
-end
\ No newline at end of file
+ has_many :revisions, :order => 'number'
+ has_one :current_revision, :class_name => 'Revision', :order => 'number DESC'
+
+ def revise(content, created_at, author)
+ revisions_size = new_record? ? 0 : revisions.size
+ if (revisions_size > 0) and content == current_revision.content
+ raise Instiki::ValidationError.new(
+ "You have tried to save page '#{name}' without changing its content")
+ end
+
+ author = Author.new(author.to_s) unless author.is_a?(Author)
+
+ # Try to render content to make sure that markup engine can take it,
+ # before addin a revision to the page
+ Revision.new(:page => self, :content => content, :created_at => created_at, :author => author).force_rendering
+
+ # A user may change a page, look at it and make some more changes - several times.
+ # Not to record every such iteration as a new revision, if the previous revision was done
+ # by the same author, not more than 30 minutes ago, then update the last revision instead of
+ # creating a new one
+ if (revisions_size > 0) && continous_revision?(created_at, author)
+ current_revision.update_attributes(:created_at => created_at, :content => content)
+ else
+ Revision.create(:page => self, :content => content, :created_at => created_at, :author => author)
+ end
+
+ self.created_at = created_at
+ save
+ web.refresh_pages_with_references(name) if revisions_size == 0
+
+ self
+ end
+
+ def rollback(revision_number, created_at, author_ip = nil)
+ roll_back_revision = Revision.find(:first, :conditions => ['page_id = ? AND number = ?', id, revision_number])
+ revise(roll_back_revision.content, created_at, Author.new(roll_back_revision.author, author_ip))
+ end
+
+ def revisions?
+ revisions.size > 1
+ end
+
+ def revised_on
+ created_on
+ end
+
+ def in_category?(cat)
+ cat.nil? || cat.empty? || categories.include?(cat)
+ end
+
+ def categories
+ display_content.find_chunks(Category).map { |cat| cat.list }.flatten
+ end
+
+ def authors
+ revisions.collect { |rev| rev.author }
+ end
+
+ def references
+ web.select.pages_that_reference(name)
+ end
+
+ def linked_from
+ web.select.pages_that_link_to(name)
+ end
+
+ def included_from
+ web.select.pages_that_include(name)
+ end
+
+ # Returns the original wiki-word name as separate words, so "MyPage" becomes "My Page".
+ def plain_name
+ web.brackets_only? ? name : WikiWords.separate(name)
+ end
+
+ # used to build chunk ids.
+ #def id
+ # @id ||= name.unpack('H*').first
+ #end
+
+ def link(options = {})
+ web.make_link(name, nil, options)
+ end
+
+ def author_link(options = {})
+ web.make_link(author, nil, options)
+ end
+
+ LOCKING_PERIOD = 30.minutes
+
+ def lock(time, locked_by)
+ update_attributes(:locked_at => time, :locked_by => locked_by)
+ end
+
+ def lock_duration(time)
+ ((time - locked_at) / 60).to_i unless locked_at.nil?
+ end
+
+ def unlock
+ update_attribute(:locked_at, nil)
+ end
+
+ def locked?(comparison_time)
+ locked_at + LOCKING_PERIOD > comparison_time unless locked_at.nil?
+ end
+
+ private
+
+ def continous_revision?(created_at, author)
+ current_revision.author == author && current_revision.created_at + 30.minutes > created_at
+ end
+
+ # Forward method calls to the current revision, so the page responds to all revision calls
+ def method_missing(method_id, *args, &block)
+ method_name = method_id.to_s
+ # Perform a hand-off to AR::Base#method_missing
+ if @attributes.include?(method_name) or md = /(=|\?|_before_type_cast)$/.match(method_name)
+ super(method_id, *args, &block)
+ else
+ current_revision.send(method_id)
+ end
+ end
+end
diff --git a/app/models/revision.rb b/app/models/revision.rb
index 017b3543..ca886245 100644
--- a/app/models/revision.rb
+++ b/app/models/revision.rb
@@ -1,3 +1,122 @@
+require 'diff'
class Revision < ActiveRecord::Base
belongs_to :page
-end
\ No newline at end of file
+ composed_of :author, :mapping => [ %w(author name), %w(ip ip) ]
+
+ def created_on
+ created_at.to_date
+ end
+
+ def pretty_created_at
+ # Must use DateTime because Time doesn't support %e on at least some platforms
+ DateTime.new(
+ created_at.year, created_at.mon, created_at.day, created_at.hour, created_at.min
+ ).strftime "%B %e, %Y %H:%M"
+ end
+
+ # todo: drop next_revision, previuous_revision and number from here - unused code
+ def next_revision
+ Revision.find_by_number_and_page_id(number+1, page_id)
+ end
+
+ def previous_revision
+ @previous_revions ||= number > 0 ? Revision.find_by_number_and_page_id(number-1, page_id) : nil
+ end
+
+ # Returns an array of all the WikiIncludes present in the content of this revision.
+ def wiki_includes
+ unless @wiki_includes_cache
+ chunks = display_content.find_chunks(Include)
+ @wiki_includes_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
+ end
+ @wiki_includes_cache
+ end
+
+ # Returns an array of all the WikiReferences present in the content of this revision.
+ def wiki_references
+ unless @wiki_references_cache
+ chunks = display_content.find_chunks(WikiChunk::WikiReference)
+ @wiki_references_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
+ end
+ @wiki_references_cache
+ end
+
+ # Returns an array of all the WikiWords present in the content of this revision.
+ def wiki_words
+ unless @wiki_words_cache
+ wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
+ @wiki_words_cache = wiki_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
+ end
+ @wiki_words_cache
+ end
+
+ # Returns an array of all the WikiWords present in the content of this revision.
+ # that already exists as a page in the web.
+ def existing_pages
+ wiki_words.select { |wiki_word| page.web.page(wiki_word) }
+ end
+
+ # Returns an array of all the WikiWords present in the content of this revision
+ # that *doesn't* already exists as a page in the web.
+ def unexisting_pages
+ wiki_words - existing_pages
+ end
+
+ # Explicit check for new type of display cache with chunks_by_type method.
+ # Ensures new version works with older snapshots.
+ def display_content
+ unless @display_cache && @display_cache.respond_to?(:chunks_by_type)
+ @display_cache = WikiContent.new(self)
+ @display_cache.render!
+ end
+ @display_cache
+ end
+
+ def display_diff
+ previous_revision ? HTMLDiff.diff(previous_revision.display_content, display_content) : display_content
+ end
+
+ def clear_display_cache
+ @wiki_words_cache = @published_cache = @display_cache = @wiki_includes_cache =
+ @wiki_references_cache = nil
+ end
+
+ def display_published
+ unless @published_cache && @published_cache.respond_to?(:chunks_by_type)
+ @published_cache = WikiContent.new(self, {:mode => :publish})
+ @published_cache.render!
+ end
+ @published_cache
+ end
+
+ def display_content_for_export
+ WikiContent.new(self, {:mode => :export} ).render!
+ end
+
+ def force_rendering
+ begin
+ display_content.render!
+ rescue => e
+ logger.error "Failed rendering page #{@name}"
+ logger.error e
+ message = e.message
+ # substitute content with an error message
+ self.content = <<-EOL
+
Markup engine has failed to render this page, raising the following error:
+
#{message}
+
#{self.content}
+ EOL
+ clear_display_cache
+ raise e
+ end
+ end
+
+ protected
+ before_create :set_revision_number
+ after_create :force_rendering
+ after_save :clear_display_cache
+
+ def set_revision_number
+ self.number = self.class.count(['page_id = ?', page_id]) + 1
+ end
+end
diff --git a/app/models/system.rb b/app/models/system.rb
new file mode 100644
index 00000000..7ac1ad08
--- /dev/null
+++ b/app/models/system.rb
@@ -0,0 +1,4 @@
+class System < ActiveRecord::Base
+ set_table_name 'system'
+ validates_presence_of :password
+end
\ No newline at end of file
diff --git a/app/models/web.rb b/app/models/web.rb
index 2c31bf8f..5ca077d5 100644
--- a/app/models/web.rb
+++ b/app/models/web.rb
@@ -1,3 +1,173 @@
+require 'cgi'
+
class Web < ActiveRecord::Base
- has_many :pages
-end
\ No newline at end of file
+ has_many :pages#, :include => [:current_revision, :web]
+
+ def wiki
+ Wiki.new
+ end
+
+ def file_yard
+ @file_yard ||= FileYard.new("#{Wiki.storage_path}/#{address}", max_upload_size)
+ end
+
+ def settings_changed?(markup, safe_mode, brackets_only)
+ self.markup != markup ||
+ self.safe_mode != safe_mode ||
+ self.brackets_only != brackets_only
+ end
+
+ def add_page(name, content, created_at, author)
+ page = page(name) || Page.new(:web => self, :name => name)
+ page.revise(content, created_at, author)
+ end
+
+ def authors
+ select.authors
+ end
+
+ def categories
+ select.map { |page| page.categories }.flatten.uniq.sort
+ end
+
+ def page(name)
+ pages.find(:first, :conditions => ['name = ?', name])
+ end
+
+ def has_page?(name)
+ Page.count(['web_id = ? AND name = ?', id, name]) > 0
+ end
+
+ def has_file?(name)
+ wiki.file_yard(self).has_file?(name)
+ end
+
+ def markup
+ read_attribute('markup').to_sym
+ end
+
+ def make_file_link(mode, name, text, base_url)
+ link = CGI.escape(name)
+ case mode
+ when :export
+ if has_file?(name) then "#{text}"
+ else "#{text}" end
+ when :publish
+ if has_file?(name) then "#{text}"
+ else "#{text}" end
+ else
+ if has_file?(name)
+ "#{text}"
+ else
+ "#{text}?"
+ end
+ end
+ end
+
+ # Create a link for the given page name and link text based
+ # on the render mode in options and whether the page exists
+ # in the this web.
+ # The links a relative, and will work only if displayed on another WikiPage.
+ # It should not be used in menus, templates and such - instead, use link_to_page helper
+ def make_link(name, text = nil, options = {})
+ text = CGI.escapeHTML(text || WikiWords.separate(name))
+ mode = options[:mode] || :show
+ base_url = options[:base_url] || '..'
+ link_type = options[:link_type] || :show
+ case link_type.to_sym
+ when :show
+ make_page_link(mode, name, text, base_url)
+ when :file
+ make_file_link(mode, name, text, base_url)
+ when :pic
+ make_pic_link(mode, name, text, base_url)
+ else
+ raise "Unknown link type: #{link_type}"
+ end
+ end
+
+ def make_page_link(mode, name, text, base_url)
+ link = CGI.escape(name)
+ case mode.to_sym
+ when :export
+ if has_page?(name) then %{#{text}}
+ else %{#{text}} end
+ when :publish
+ if has_page?(name) then %{#{text}}
+ else %{#{text}} end
+ else
+ if has_page?(name)
+ %{#{text}}
+ else
+ %{#{text}?}
+ end
+ end
+ end
+
+ def make_pic_link(mode, name, text, base_url)
+ link = CGI.escape(name)
+ case mode.to_sym
+ when :export
+ if has_file?(name) then %{}
+ else %{} end
+ when :publish
+ if has_file?(name) then %{}
+ else %{#{text}} end
+ else
+ if has_file?(name) then %{}
+ else %{#{text}?} end
+ end
+ end
+
+ # Clears the display cache for all the pages with references to
+ def refresh_pages_with_references(page_name)
+ #select.pages_that_reference(page_name).each { |page|
+ # page.revisions.each { |revision| revision.clear_display_cache }
+ #}
+ end
+
+ def refresh_revisions
+ select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
+ end
+
+ def remove_pages(pages_to_be_removed)
+ pages_to_be_removed.each { |p| p.destroy }
+ end
+
+ def revised_on
+ select.most_recent_revision
+ end
+
+ def select(&condition)
+ PageSet.new(self, pages, condition)
+ end
+
+ private
+
+ # Returns an array of all the wiki words in any current revision
+ def wiki_words
+ pages.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
+ end
+
+ # Returns an array of all the page names on this web
+ def page_names
+ pages.map { |p| p.name }
+ end
+
+ protected
+ before_save :sanitize_markup
+ before_validation :validate_address
+ validates_uniqueness_of :address
+ validates_length_of :color, :in => 3..6
+
+ def sanitize_markup
+ self.markup = markup.to_s
+ end
+
+ def validate_address
+ unless address == CGI.escape(address)
+ self.errors.add(:address, 'should contain only valid URI characters')
+ raise Instiki::ValidationError.new("#{self.class.human_attribute_name('address')} #{errors.on(:address)}")
+ end
+ end
+end
diff --git a/app/views/wiki/list.rhtml b/app/views/wiki/list.rhtml
index 34a93798..d891f5a2 100644
--- a/app/views/wiki/list.rhtml
+++ b/app/views/wiki/list.rhtml
@@ -17,7 +17,7 @@
<% end %>
-<% if @web.count_pages %>
+<% if @web.count_pages? %>
<% total_chars = @pages_in_category.characters %>
",
@home.display_content
end
def test_uploads_blocking
- @web.allow_uploads = true
+ set_web_property :allow_uploads, true
r = process 'file', 'web' => 'wiki1', 'id' => 'filename'
- assert_success
+ assert_response :success
- @web.allow_uploads = false
+ set_web_property :allow_uploads, false
r = process 'file', 'web' => 'wiki1', 'id' => 'filename'
assert_equal '403 Forbidden', r.headers['Status']
end
diff --git a/test/functional/routes_test.rb b/test/functional/routes_test.rb
index 2e338bd0..c2334ef7 100644
--- a/test/functional/routes_test.rb
+++ b/test/functional/routes_test.rb
@@ -1,4 +1,4 @@
-#!/bin/env ruby -w
+#!/bin/env ruby
require File.dirname(__FILE__) + '/../test_helper'
diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb
index bc79a8bf..b799ad3b 100755
--- a/test/functional/wiki_controller_test.rb
+++ b/test/functional/wiki_controller_test.rb
@@ -1,10 +1,10 @@
-#!/bin/env ruby -w
+#!/bin/env ruby
# Uncomment the line below to enable pdflatex tests; don't forget to comment them again
# commiting to SVN
# $INSTIKI_TEST_PDFLATEX = true
-require File.dirname(__FILE__) + '/../test_helper'
+require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
require 'wiki_controller'
require 'rexml/document'
require 'tempfile'
@@ -14,63 +14,60 @@ require 'zip/zipfilesystem'
class WikiController; def rescue_action(e) logger.error(e); raise e end; end
class WikiControllerTest < Test::Unit::TestCase
-
+ fixtures :webs, :pages, :revisions, :system
+
def setup
- setup_test_wiki
- setup_controller_test
+ @controller = WikiController.new
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+ @wiki = Wiki.new
+ @web = webs(:test_wiki)
+ @home = @page = pages(:home_page)
+ @oak = pages(:oak)
+ @elephant = pages(:elephant)
end
- def tear_down
- tear_down_wiki
- end
-
-
def test_authenticate
- @web.password = 'pswd'
+ set_web_property :password, 'pswd'
- r = process('authenticate', 'web' => 'wiki1', 'password' => 'pswd')
+ get :authenticate, :web => 'wiki1', :password => 'pswd'
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
- assert_equal ['pswd'], r.cookies['web_address']
+ assert_equal ['pswd'], @response.cookies['web_address']
end
def test_authenticate_wrong_password
- @web.password = 'pswd'
+ set_web_property :password, 'pswd'
r = process('authenticate', 'web' => 'wiki1', 'password' => 'wrong password')
assert_redirected_to :action => 'login', :web => 'wiki1'
assert_nil r.cookies['web_address']
end
-
def test_authors
- setup_wiki_with_three_pages
@wiki.write_page('wiki1', 'BreakSortingOrder',
"This page breaks the accidentally correct sorting order of authors",
Time.now, Author.new('BreakingTheOrder', '127.0.0.2'))
r = process('authors', 'web' => 'wiki1')
- assert_success
- assert_equal ['AnAuthor', 'BreakingTheOrder', 'Guest', 'TreeHugger'],
+ assert_response :success
+ assert_equal %w(AnAuthor BreakingTheOrder DavidHeinemeierHansson Guest Me TreeHugger),
r.template_objects['authors']
end
-
def test_cancel_edit
- setup_wiki_with_three_pages
@oak.lock(Time.now, 'Locky')
assert @oak.locked?(Time.now)
r = process('cancel_edit', 'web' => 'wiki1', 'id' => 'Oak')
assert_redirected_to :action => 'show', :id => 'Oak'
- assert !@oak.locked?(Time.now)
+ assert !Page.find(@oak.id).locked?(Time.now)
end
-
def test_edit
r = process 'edit', 'web' => 'wiki1', 'id' => 'HomePage'
- assert_success
+ assert_response :success
assert_equal @wiki.read_page('wiki1', 'HomePage'), r.template_objects['page']
end
@@ -83,7 +80,8 @@ class WikiControllerTest < Test::Unit::TestCase
def test_edit_page_break_lock
@home.lock(Time.now, 'Locky')
process 'edit', 'web' => 'wiki1', 'id' => 'HomePage', 'break_lock' => 'y'
- assert_success
+ assert_response :success
+ @home = Page.find(@home.id)
assert @home.locked?(Time.now)
end
@@ -99,19 +97,17 @@ class WikiControllerTest < Test::Unit::TestCase
Time.now, Author.new('Special', '127.0.0.3'))
r = process 'edit', 'web' => 'wiki1', 'id' => 'With : Special /> symbols'
- assert_success
+ assert_response :success
xml = REXML::Document.new(r.body)
form = REXML::XPath.first(xml, '//form')
assert_equal '/wiki1/save/With+%3A+Special+%2F%3E+symbols', form.attributes['action']
end
-
def test_export_html
- setup_wiki_with_three_pages
-
+ @home.rollback(1, Time.now, 'Rick') # much simpler regex statement to match
r = process 'export_html', 'web' => 'wiki1'
- assert_success
+ assert_response :success
assert_equal 'application/zip', r.headers['Content-Type']
assert_match /attachment; filename="wiki1-html-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.zip"/,
r.headers['Content-Disposition']
@@ -124,7 +120,7 @@ class WikiControllerTest < Test::Unit::TestCase
begin
File.open(@tempfile_path, 'wb') { |f| f.write(content); @exported_file = f.path }
Zip::ZipFile.open(@exported_file) do |zip|
- assert_equal %w(Elephant.html HomePage.html Oak.html index.html), zip.dir.entries('.').sort
+ assert_equal %w(Elephant.html FirstPage.html HomePage.html MyWay.html NoWikiWord.html Oak.html SmartEngine.html ThatWay.html index.html), zip.dir.entries('.').sort
assert_match /.*/,
zip.file.read('Elephant.html').gsub(/\s+/, ' ')
assert_match /.*/,
@@ -138,12 +134,10 @@ class WikiControllerTest < Test::Unit::TestCase
end
end
- def test_export_html_no_layout
- setup_wiki_with_three_pages
-
+ def test_export_html_no_layout
r = process 'export_html', 'web' => 'wiki1', 'layout' => 'no'
- assert_success
+ assert_response :success
assert_equal 'application/zip', r.headers['Content-Type']
assert_match /attachment; filename="wiki1-html-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.zip"/,
r.headers['Content-Disposition']
@@ -155,7 +149,7 @@ class WikiControllerTest < Test::Unit::TestCase
def test_export_markup
r = process 'export_markup', 'web' => 'wiki1'
- assert_success
+ assert_response :success
assert_equal 'application/zip', r.headers['Content-Type']
assert_match /attachment; filename="wiki1-textile-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.zip"/,
r.headers['Content-Disposition']
@@ -168,7 +162,7 @@ class WikiControllerTest < Test::Unit::TestCase
def test_export_pdf
r = process 'export_pdf', 'web' => 'wiki1'
- assert_success
+ assert_response :success
assert_equal 'application/pdf', r.headers['Content-Type']
assert_match /attachment; filename="wiki1-tex-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.pdf"/,
r.headers['Content-Disposition']
@@ -183,13 +177,10 @@ class WikiControllerTest < Test::Unit::TestCase
puts ' $INSTIKI_TEST_PDFLATEX to enable them.'
end
-
- def test_export_tex
- setup_wiki_with_three_pages
-
+ def test_export_tex
r = process 'export_tex', 'web' => 'wiki1'
- assert_success
+ assert_response :success
assert_equal 'application/octet-stream', r.headers['Content-Type']
assert_match /attachment; filename="wiki1-tex-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.tex"/,
r.headers['Content-Disposition']
@@ -202,6 +193,8 @@ class WikiControllerTest < Test::Unit::TestCase
end
def test_index
+ # delete extra web fixture
+ webs(:instiki).destroy
process('index')
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
end
@@ -219,41 +212,39 @@ class WikiControllerTest < Test::Unit::TestCase
end
def test_index_wiki_not_initialized
- ApplicationController.wiki = WikiServiceWithNoPersistence.new
+ use_blank_wiki
process('index')
assert_redirected_to :controller => 'admin', :action => 'create_system'
end
def test_list
- setup_wiki_with_three_pages
-
r = process('list', 'web' => 'wiki1')
assert_equal ['animals', 'trees'], r.template_objects['categories']
assert_nil r.template_objects['category']
- assert_equal [@elephant, @home, @oak], r.template_objects['pages_in_category']
+ assert_equal [@elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word), @oak, pages(:smart_engine), pages(:that_way)], r.template_objects['pages_in_category']
end
def test_locked
@home.lock(Time.now, 'Locky')
r = process('locked', 'web' => 'wiki1', 'id' => 'HomePage')
- assert_success
+ assert_response :success
assert_equal @home, r.template_objects['page']
end
def test_login
r = process 'login', 'web' => 'wiki1'
- assert_success
+ assert_response :success
# this action goes straight to the templates
end
def test_new
r = process('new', 'id' => 'NewPage', 'web' => 'wiki1')
- assert_success
+ assert_response :success
assert_equal 'AnonymousCoward', r.template_objects['author']
assert_equal 'NewPage', r.template_objects['page_name']
end
@@ -264,7 +255,7 @@ class WikiControllerTest < Test::Unit::TestCase
def test_pdf
assert RedClothForTex.available?, 'Cannot do test_pdf when pdflatex is not available'
r = process('pdf', 'web' => 'wiki1', 'id' => 'HomePage')
- assert_success
+ assert_response :success
content = r.binary_content
@@ -282,23 +273,23 @@ class WikiControllerTest < Test::Unit::TestCase
def test_print
r = process('print', 'web' => 'wiki1', 'id' => 'HomePage')
- assert_success
+ assert_response :success
assert_equal :show, r.template_objects['link_mode']
end
def test_published
- @web.published = true
+ set_web_property :published, true
r = process('published', 'web' => 'wiki1', 'id' => 'HomePage')
- assert_success
+ assert_response :success
assert_equal @home, r.template_objects['page']
end
def test_published_web_not_published
- @web.published = false
+ set_web_property :published, false
r = process('published', 'web' => 'wiki1', 'id' => 'HomePage')
@@ -308,11 +299,11 @@ class WikiControllerTest < Test::Unit::TestCase
def test_recently_revised
r = process('recently_revised', 'web' => 'wiki1')
- assert_success
+ assert_response :success
- assert_equal [], r.template_objects['categories']
+ assert_equal %w(animals trees), r.template_objects['categories']
assert_nil r.template_objects['category']
- assert_equal [@home], r.template_objects['pages_in_category']
+ assert_equal [@elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word), @oak, pages(:smart_engine), pages(:that_way)], r.template_objects['pages_in_category']
assert_equal 'the web', r.template_objects['set_name']
end
@@ -323,37 +314,33 @@ class WikiControllerTest < Test::Unit::TestCase
Time.now, Author.new('AnotherAuthor', '127.0.0.2'))
r = process('recently_revised', 'web' => 'wiki1')
- assert_success
+ assert_response :success
- assert_equal ['categorized'], r.template_objects['categories']
+ assert_equal %w(animals categorized trees), r.template_objects['categories']
# no category is specified in params
assert_nil r.template_objects['category']
- assert_equal [@home, page2], r.template_objects['pages_in_category'],
+ assert_equal [@elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word), @oak, page2, pages(:smart_engine), pages(:that_way)], r.template_objects['pages_in_category'],
"Pages are not as expected: " +
r.template_objects['pages_in_category'].map {|p| p.name}.inspect
assert_equal 'the web', r.template_objects['set_name']
end
def test_recently_revised_with_categorized_page_multiple_categories
- setup_wiki_with_three_pages
-
r = process('recently_revised', 'web' => 'wiki1')
- assert_success
+ assert_response :success
assert_equal ['animals', 'trees'], r.template_objects['categories']
# no category is specified in params
assert_nil r.template_objects['category']
- assert_equal [@elephant, @home, @oak], r.template_objects['pages_in_category'],
+ assert_equal [@elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word), @oak, pages(:smart_engine), pages(:that_way)], r.template_objects['pages_in_category'],
"Pages are not as expected: " +
r.template_objects['pages_in_category'].map {|p| p.name}.inspect
assert_equal 'the web', r.template_objects['set_name']
end
def test_recently_revised_with_specified_category
- setup_wiki_with_three_pages
-
r = process('recently_revised', 'web' => 'wiki1', 'category' => 'animals')
- assert_success
+ assert_response :success
assert_equal ['animals', 'trees'], r.template_objects['categories']
# no category is specified in params
@@ -366,7 +353,7 @@ class WikiControllerTest < Test::Unit::TestCase
def test_revision
r = process 'revision', 'web' => 'wiki1', 'id' => 'HomePage', 'rev' => '0'
- assert_success
+ assert_response :success
assert_equal @home, r.template_objects['page']
assert_equal @home.revisions[0], r.template_objects['revision']
end
@@ -377,27 +364,24 @@ class WikiControllerTest < Test::Unit::TestCase
# its assigns the same as or revision
r = process 'rollback', 'web' => 'wiki1', 'id' => 'HomePage', 'rev' => '0'
- assert_success
+ assert_response :success
assert_equal @home, r.template_objects['page']
assert_equal @home.revisions[0], r.template_objects['revision']
end
def test_rss_with_content
- setup_wiki_with_three_pages
-
r = process 'rss_with_content', 'web' => 'wiki1'
- assert_success
+ assert_response :success
pages = r.template_objects['pages_by_revision']
- assert_equal [@home, @oak, @elephant], pages,
+ assert_equal [@elephant, @oak, pages(:no_wiki_word), pages(:that_way), pages(:smart_engine), pages(:my_way), pages(:first_page), @home], pages,
"Pages are not as expected: #{pages.map {|p| p.name}.inspect}"
assert !r.template_objects['hide_description']
end
def test_rss_with_content_when_blocked
- setup_wiki_with_three_pages
- @web.password = 'aaa'
- @web.published = false
+ @web.update_attributes(:password => 'aaa', :published => false)
+ @web = Web.find(@web.id)
r = process 'rss_with_content', 'web' => 'wiki1'
@@ -406,7 +390,6 @@ class WikiControllerTest < Test::Unit::TestCase
def test_rss_with_headlines
- setup_wiki_with_three_pages
@title_with_spaces = @wiki.write_page('wiki1', 'Title With Spaces',
'About spaces', 1.hour.ago, Author.new('TreeHugger', '127.0.0.2'))
@@ -415,19 +398,24 @@ class WikiControllerTest < Test::Unit::TestCase
r = process 'rss_with_headlines', 'web' => 'wiki1'
- assert_success
+ assert_response :success
pages = r.template_objects['pages_by_revision']
- assert_equal [@home, @oak, @elephant, @title_with_spaces], pages,
- "Pages are not as expected: #{pages.map {|p| p.name}.inspect}"
+ assert_equal [@elephant, @title_with_spaces, @oak, pages(:no_wiki_word), pages(:that_way), pages(:smart_engine), pages(:my_way), pages(:first_page), @home], pages, "Pages are not as expected: #{pages.map {|p| p.name}.inspect}"
assert r.template_objects['hide_description']
xml = REXML::Document.new(r.body)
expected_page_links =
- ['http://localhost:8080/wiki1/show/HomePage',
+ ['http://localhost:8080/wiki1/show/Elephant',
+ 'http://localhost:8080/wiki1/show/Title+With+Spaces',
'http://localhost:8080/wiki1/show/Oak',
- 'http://localhost:8080/wiki1/show/Elephant',
- 'http://localhost:8080/wiki1/show/Title+With+Spaces']
+ 'http://localhost:8080/wiki1/show/NoWikiWord',
+ 'http://localhost:8080/wiki1/show/ThatWay',
+ 'http://localhost:8080/wiki1/show/SmartEngine',
+ 'http://localhost:8080/wiki1/show/MyWay',
+ 'http://localhost:8080/wiki1/show/FirstPage',
+ 'http://localhost:8080/wiki1/show/HomePage',
+ ]
assert_template_xpath_match '/rss/channel/link',
'http://localhost:8080/wiki1/show/HomePage'
@@ -436,22 +424,26 @@ class WikiControllerTest < Test::Unit::TestCase
end
def test_rss_switch_links_to_published
- setup_wiki_with_three_pages
- @web.password = 'aaa'
- @web.published = true
+ @web.update_attributes(:password => 'aaa', :published => true)
+ @web = Web.find(@web.id)
@request.host = 'foo.bar.info'
@request.port = 80
r = process 'rss_with_headlines', 'web' => 'wiki1'
- assert_success
+ assert_response :success
xml = REXML::Document.new(r.body)
expected_page_links =
- ['http://foo.bar.info/wiki1/published/HomePage',
+ ['http://foo.bar.info/wiki1/published/Elephant',
'http://foo.bar.info/wiki1/published/Oak',
- 'http://foo.bar.info/wiki1/published/Elephant']
+ 'http://foo.bar.info/wiki1/published/NoWikiWord',
+ 'http://foo.bar.info/wiki1/published/ThatWay',
+ 'http://foo.bar.info/wiki1/published/SmartEngine',
+ 'http://foo.bar.info/wiki1/published/MyWay',
+ 'http://foo.bar.info/wiki1/published/FirstPage',
+ 'http://foo.bar.info/wiki1/published/HomePage']
assert_template_xpath_match '/rss/channel/link',
'http://foo.bar.info/wiki1/published/HomePage'
@@ -463,45 +455,43 @@ class WikiControllerTest < Test::Unit::TestCase
setup_wiki_with_30_pages
r = process 'rss_with_headlines', 'web' => 'wiki1'
- assert_success
+ assert_response :success
pages = r.template_objects['pages_by_revision']
assert_equal 15, pages.size, 15
r = process 'rss_with_headlines', 'web' => 'wiki1', 'limit' => '5'
- assert_success
+ assert_response :success
pages = r.template_objects['pages_by_revision']
assert_equal 5, pages.size
r = process 'rss_with_headlines', 'web' => 'wiki1', 'limit' => '25'
- assert_success
+ assert_response :success
pages = r.template_objects['pages_by_revision']
assert_equal 25, pages.size
r = process 'rss_with_headlines', 'web' => 'wiki1', 'limit' => 'all'
- assert_success
+ assert_response :success
pages = r.template_objects['pages_by_revision']
- assert_equal 31, pages.size
+ assert_equal 38, pages.size
r = process 'rss_with_headlines', 'web' => 'wiki1', 'start' => '1976-10-16'
- assert_success
+ assert_response :success
pages = r.template_objects['pages_by_revision']
- assert_equal 16, pages.size
+ assert_equal 23, pages.size
r = process 'rss_with_headlines', 'web' => 'wiki1', 'end' => '1976-10-16'
- assert_success
+ assert_response :success
pages = r.template_objects['pages_by_revision']
assert_equal 15, pages.size
r = process 'rss_with_headlines', 'web' => 'wiki1', 'start' => '1976-10-01', 'end' => '1976-10-06'
- assert_success
+ assert_response :success
pages = r.template_objects['pages_by_revision']
assert_equal 5, pages.size
end
def test_rss_title_with_ampersand
- # was ticket:143
- setup_wiki_with_three_pages
-
+ # was ticket:143
@wiki.write_page('wiki1', 'Title&With&Ampersands',
'About spaces', 1.hour.ago, Author.new('NitPicker', '127.0.0.3'))
@@ -511,15 +501,12 @@ class WikiControllerTest < Test::Unit::TestCase
assert r.body.include?('Title&With&Ampersands')
end
- def test_rss_timestamp
- setup_wiki_with_three_pages
-
+ def test_rss_timestamp
new_page = @wiki.write_page('wiki1', 'PageCreatedAtTheBeginningOfCtime',
'Created on 1 Jan 1970 at 0:00:00 Z', Time.at(0), Author.new('NitPicker', '127.0.0.3'))
r = process 'rss_with_headlines', 'web' => 'wiki1'
-
- assert_template_xpath_match '/rss/channel/item/pubDate[4]', "Thu, 01 Jan 1970 00:00:00 Z"
+ assert_template_xpath_match '/rss/channel/item/pubDate[9]', "Thu, 01 Jan 1970 00:00:00 Z"
end
def test_save
@@ -535,6 +522,7 @@ class WikiControllerTest < Test::Unit::TestCase
def test_save_new_revision_of_existing_page
@home.lock(Time.now, 'Batman')
+ current_revisions = @home.revisions.size
r = process 'save', 'web' => 'wiki1', 'id' => 'HomePage', 'content' => 'Revised HomePage',
'author' => 'Batman'
@@ -542,8 +530,7 @@ class WikiControllerTest < Test::Unit::TestCase
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
assert_equal ['Batman'], r.cookies['author'].value
home_page = @wiki.read_page('wiki1', 'HomePage')
- assert_equal [home_page], @web.pages.values
- assert_equal 2, home_page.revisions.size
+ assert_equal current_revisions+1, home_page.revisions.size
assert_equal 'Revised HomePage', home_page.content
assert_equal 'Batman', home_page.author
assert !home_page.locked?(Time.now)
@@ -563,57 +550,47 @@ class WikiControllerTest < Test::Unit::TestCase
revisions_after = @home.revisions.size
assert_equal revisions_before, revisions_after
+ @home = Page.find(@home.id)
assert !@home.locked?(Time.now), 'HomePage should be unlocked if an edit was unsuccessful'
end
def test_search
- setup_wiki_with_three_pages
-
r = process 'search', 'web' => 'wiki1', 'query' => '\s[A-Z]ak'
assert_redirected_to :action => 'show', :id => 'Oak'
end
def test_search_multiple_results
- setup_wiki_with_three_pages
-
r = process 'search', 'web' => 'wiki1', 'query' => 'All about'
- assert_success
+ assert_response :success
assert_equal 'All about', r.template_objects['query']
assert_equal [@elephant, @oak], r.template_objects['results']
assert_equal [], r.template_objects['title_results']
end
def test_search_by_content_and_title
- setup_wiki_with_three_pages
-
r = process 'search', 'web' => 'wiki1', 'query' => '(Oak|Elephant)'
- assert_success
+ assert_response :success
assert_equal '(Oak|Elephant)', r.template_objects['query']
assert_equal [@elephant, @oak], r.template_objects['results']
assert_equal [@elephant, @oak], r.template_objects['title_results']
end
def test_search_zero_results
- setup_wiki_with_three_pages
-
r = process 'search', 'web' => 'wiki1', 'query' => 'non-existant text'
- assert_success
+ assert_response :success
assert_equal [], r.template_objects['results']
assert_equal [], r.template_objects['title_results']
end
-
-
-
def test_show_page
- r = process('show', 'id' => 'HomePage', 'web' => 'wiki1')
- assert_success
- assert_match /First revision of the end/, r.body
+ r = process('show', 'id' => 'Oak', 'web' => 'wiki1')
+ assert_response :success
+ assert_tag :content => /All about oak/
end
def test_show_page_with_multiple_revisions
@@ -622,7 +599,7 @@ class WikiControllerTest < Test::Unit::TestCase
r = process('show', 'id' => 'HomePage', 'web' => 'wiki1')
- assert_success
+ assert_response :success
assert_match /Second revision of the end/, r.body
end
@@ -633,24 +610,25 @@ class WikiControllerTest < Test::Unit::TestCase
def test_show_no_page
r = process('show', 'id' => '', 'web' => 'wiki1')
- assert_equal 404, r.response_code
+ assert_response :missing
r = process('show', 'web' => 'wiki1')
- assert_equal 404, r.response_code
+ assert_response :missing
end
def test_tex
r = process('tex', 'web' => 'wiki1', 'id' => 'HomePage')
- assert_success
+ assert_response :success
assert_equal "\\documentclass[12pt,titlepage]{article}\n\n\\usepackage[danish]{babel} " +
"%danske tekster\n\\usepackage[OT1]{fontenc} %rigtige danske bogstaver...\n" +
"\\usepackage{a4}\n\\usepackage{graphicx}\n\\usepackage{ucs}\n\\usepackage[utf8x]" +
"{inputenc}\n\\input epsf \n\n%----------------------------------------------------" +
"---------------\n\n\\begin{document}\n\n\\sloppy\n\n%-----------------------------" +
- "--------------------------------------\n\n\\section*{HomePage}\n\nFirst revision of " +
- "the HomePage end\n\n\\end{document}", r.body
+ "--------------------------------------\n\n\\section*{HomePage}\n\nHisWay would be " +
+ "MyWay in kinda ThatWay in HisWay though MyWay \\OverThere -- see SmartEngine in that " +
+ "SmartEngineGUI\n\n\\end{document}", r.body
end
@@ -659,8 +637,8 @@ class WikiControllerTest < Test::Unit::TestCase
r = process('web_list')
- assert_success
- assert_equal [another_wiki, @web], r.template_objects['webs']
+ assert_response :success
+ assert_equal [another_wiki, webs(:instiki), @web], r.template_objects['webs']
end
end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 19219ce7..0b29f757 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -10,17 +10,97 @@ require 'active_record/fixtures'
require 'action_controller/test_process'
require 'action_web_service/test_invoke'
require 'breakpoint'
+require 'wiki_content'
+# Uncomment these and hang on, because the tests will be FAST
+#Test::Unit::TestCase.pre_loaded_fixtures = false
+#Test::Unit::TestCase.use_transactional_fixtures = true
+
+Test::Unit::TestCase.use_instantiated_fixtures = false
Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
class Test::Unit::TestCase
- # Turn these on to use transactional fixtures with table_name(:fixture_name) instantiation of fixtures
- # self.use_transactional_fixtures = true
- # self.use_instantiated_fixtures = false
-
def create_fixtures(*table_names)
Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures", table_names)
end
# Add more helper methods to be used by all tests here...
-end
\ No newline at end of file
+ def set_web_property(property, value)
+ @web.update_attribute(property, value)
+ @page = Page.find(@page.id)
+ @wiki.webs[@web.name] = @web
+ end
+
+ def setup_wiki_with_30_pages
+ ActiveRecord::Base.silence do
+ (1..30).each do |i|
+ @wiki.write_page('wiki1', "page#{i}", "Test page #{i}\ncategory: test",
+ Time.local(1976, 10, i, 12, 00, 00), Author.new('Dema', '127.0.0.2'))
+ end
+ end
+ @web = Web.find(@web.id)
+ end
+
+ def use_blank_wiki
+ Revision.destroy_all
+ Page.destroy_all
+ Web.destroy_all
+ end
+end
+
+# This module is to be included in unit tests that involve matching chunks.
+# It provides a easy way to test whether a chunk matches a particular string
+# and any the values of any fields that should be set after a match.
+class ContentStub < String
+ include ChunkManager
+ def initialize(str)
+ super
+ init_chunk_manager
+ end
+ def page_link(*); end
+end
+
+module ChunkMatch
+
+ # Asserts a number of tests for the given type and text.
+ def match(chunk_type, test_text, expected_chunk_state)
+ if chunk_type.respond_to? :pattern
+ assert_match(chunk_type.pattern, test_text)
+ end
+
+ content = ContentStub.new(test_text)
+ chunk_type.apply_to(content)
+
+ # Test if requested parts are correct.
+ expected_chunk_state.each_pair do |a_method, expected_value|
+ assert content.chunks.last.kind_of?(chunk_type)
+ assert_respond_to(content.chunks.last, a_method)
+ assert_equal(expected_value, content.chunks.last.send(a_method.to_sym),
+ "Wrong #{a_method} value")
+ end
+ end
+
+ # Asserts that test_text doesn't match the chunk_type
+ def no_match(chunk_type, test_text)
+ if chunk_type.respond_to? :pattern
+ assert_no_match(chunk_type.pattern, test_text)
+ end
+ end
+end
+
+if defined? $validate_xml_in_assert_success and $validate_xml_in_assert_success == true
+ module Test
+ module Unit
+ module Assertions
+ unless method_defined? :__assert_success_before_override_by_instiki
+ alias :__assert_success_before_override_by_instiki :assert_success
+ end
+ def assert_success
+ __assert_success_before_override_by_instiki
+ if @response.body.kind_of?(Proc) then # it's a file download, not an HTML content
+ else assert_nothing_raised(@response.body) { REXML::Document.new(@response.body) } end
+ end
+ end
+ end
+ end
+end
diff --git a/test/unit/diff_test.rb b/test/unit/diff_test.rb
index 3a0f35a5..90d0e79c 100755
--- a/test/unit/diff_test.rb
+++ b/test/unit/diff_test.rb
@@ -1,6 +1,6 @@
-#!/bin/env ruby -w
+#!/bin/env ruby
-require File.dirname(__FILE__) + '/../test_helper'
+require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
require 'diff'
include Diff
diff --git a/test/unit/file_yard_test.rb b/test/unit/file_yard_test.rb
index f40c0588..9d76bd7c 100755
--- a/test/unit/file_yard_test.rb
+++ b/test/unit/file_yard_test.rb
@@ -1,4 +1,4 @@
-#!/bin/env ruby -w
+#!/bin/env ruby
require File.dirname(__FILE__) + '/../test_helper'
require 'fileutils'
@@ -67,4 +67,4 @@ class FileYardTest < Test::Unit::TestCase
"#{RAILS_ROOT}/storage/test/instiki"
end
-end
\ No newline at end of file
+end
diff --git a/test/unit/page_test.rb b/test/unit/page_test.rb
index 8af94246..02380175 100644
--- a/test/unit/page_test.rb
+++ b/test/unit/page_test.rb
@@ -1,7 +1,78 @@
-require File.dirname(__FILE__) + '/../test_helper'
+require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
class PageTest < Test::Unit::TestCase
-
- fixtures 'webs', 'pages', 'revisions'
+ fixtures :webs, :pages, :revisions, :system
+ def setup
+ @page = pages(:first_page)
+ end
+
+ def test_lock
+ assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
+
+ @page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
+
+ assert @page.locked?(Time.local(2004, 4, 4, 16, 50))
+ assert !@page.locked?(Time.local(2004, 4, 4, 17, 1))
+
+ @page.unlock
+
+ assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
+ end
+
+ def test_lock_duration
+ @page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
+
+ assert_equal 15, @page.lock_duration(Time.local(2004, 4, 4, 16, 45))
+ end
+
+ def test_plain_name
+ assert_equal "First Page", @page.plain_name
+ end
+
+ def test_revise
+ @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
+ assert_equal 2, @page.revisions(true).length, 'Should have two revisions'
+ assert_equal 'MarianneSyhler', @page.current_revision(true).author.to_s, 'Mary should be the author now'
+ assert_equal 'DavidHeinemeierHansson', @page.revisions.first.author.to_s, 'David was the first author'
+ end
+
+ def test_revise_continous_revision
+ @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
+ assert_equal 2, @page.revisions(true).length
+
+ @page.current_revision(true)
+ @page.revise('HisWay would be MyWay in kinda update', Time.local(2004, 4, 4, 16, 57), 'MarianneSyhler')
+ assert_equal 2, @page.revisions(true).length
+ assert_equal 'HisWay would be MyWay in kinda update', @page.revisions.last.content
+ assert_equal Time.local(2004, 4, 4, 16, 57), @page.revisions.last.created_at
+
+ @page.revise('HisWay would be MyWay in the house', Time.local(2004, 4, 4, 16, 58), 'DavidHeinemeierHansson')
+ assert_equal 3, @page.revisions(true).length
+ assert_equal 'HisWay would be MyWay in the house', @page.revisions.last.content
+
+ @page.revise('HisWay would be MyWay in my way', Time.local(2004, 4, 4, 17, 30), 'DavidHeinemeierHansson')
+ assert_equal 4, @page.revisions(true).length
+ end
+
+ def test_revise_content_unchanged
+ last_revision_before = @page.current_revision
+ revisions_number_before = @page.revisions.size
+
+ assert_raises(Instiki::ValidationError) {
+ @page.revise(@page.current_revision.content, Time.now, 'AlexeyVerkhovsky')
+ }
+
+ assert_equal last_revision_before, @page.current_revision(true)
+ assert_equal revisions_number_before, @page.revisions.size
+ end
+
+ def test_rollback
+ @page.revise("spot two", Time.now, "David")
+ @page.revise("spot three", Time.now + 2000, "David")
+ assert_equal 3, @page.revisions(true).length, "Should have three revisions"
+ @page.current_revision(true)
+ @page.rollback(1, Time.now)
+ assert_equal "HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\\\OverThere -- see SmartEngine in that SmartEngineGUI", @page.current_revision(true).content
+ end
end
diff --git a/test/unit/redcloth_for_tex_test.rb b/test/unit/redcloth_for_tex_test.rb
index 82270303..d15071a0 100755
--- a/test/unit/redcloth_for_tex_test.rb
+++ b/test/unit/redcloth_for_tex_test.rb
@@ -1,4 +1,4 @@
-#!/bin/env ruby -w
+#!/bin/env ruby
require File.dirname(__FILE__) + '/../test_helper'
require 'redcloth_for_tex'
@@ -66,4 +66,4 @@ EOL
def test_subsection_depth
assert_equal "\\subsubsection*{Hello}", RedClothForTex.new("h4. Hello").to_tex
end
-end
\ No newline at end of file
+end
diff --git a/test/unit/revision_test.rb b/test/unit/revision_test.rb
index 0024c6b3..c3f588fa 100644
--- a/test/unit/revision_test.rb
+++ b/test/unit/revision_test.rb
@@ -1,7 +1,315 @@
-require File.dirname(__FILE__) + '/../test_helper'
+require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
class RevisionTest < Test::Unit::TestCase
+ fixtures :webs, :pages, :revisions, :system
- fixtures 'webs', 'pages', 'revisions'
+ def setup
+ @wiki = Wiki.new
+ @web = webs(:test_wiki)
+ @page = pages(:home_page)
+ @revision = revisions(:home_page_second_revision)
+ end
+
+ def test_wiki_words
+ assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ), @revision.wiki_words.sort
+
+ @wiki.write_page('wiki1', 'NoWikiWord', 'hey you!', Time.now, 'Me')
+ assert_equal [], @wiki.read_page('wiki1', 'NoWikiWord').wiki_words
+ end
+ def test_existing_pages
+ assert_equal %w( MyWay SmartEngine ThatWay ), @revision.existing_pages.sort
+ end
+
+ def test_unexisting_pages
+ assert_equal %w( HisWay SmartEngineGUI ), @revision.unexisting_pages.sort
+ end
+
+ def test_content_with_wiki_links
+ assert_equal '
His Way? ' +
+ 'would be My Way in kinda ' +
+ 'That Way in ' +
+ 'His Way? ' +
+ 'though My Way OverThere—see ' +
+ 'Smart Engine in that ' +
+ 'Smart Engine GUI' +
+ '?
',
+ '("What is a wiki?":http://wiki.org/wiki.cgi?WhatIsWiki)')
+ end
+
+ def test_content_with_image_link
+ assert_markup_parsed_as(
+ '
This is a Textile image link.
',
+ 'This !http://hobix.com/sample.jpg! is a Textile image link.')
+ end
+
+ def test_content_with_inlined_img_tag
+ assert_markup_parsed_as(
+ '
This is an inline image link.
',
+ 'This is an inline image link.')
+
+ assert_markup_parsed_as(
+ '
This is an inline image link.
',
+ 'This is an inline image link.')
+ end
+
+ def test_nowiki_tag
+ assert_markup_parsed_as(
+ '
Do not mark up [[this text]] or http://www.thislink.com.
',
+ 'Do not mark up [[this text]] ' +
+ 'or http://www.thislink.com.')
+ end
+
+ def test_multiline_nowiki_tag
+ assert_markup_parsed_as(
+ "
Do not mark \n up [[this text]] \nand http://this.url.com but markup " +
+ 'this?
',
+ "Do not mark \n up [[this text]] \n" +
+ "and http://this.url.com but markup [[this]]")
+ end
+
+ def test_content_with_bracketted_wiki_word
+ set_web_property :brackets_only, true
+ assert_markup_parsed_as(
+ '
This is a WikiWord and a tricky name ' +
+ 'Sperberg-McQueen?.
',
+ 'This is a WikiWord and a tricky name [[Sperberg-McQueen]].')
+ end
+
+ def test_content_for_export
+ assert_equal '
His Way would be ' +
+ 'My Way in kinda ' +
+ 'That Way in ' +
+ 'His Way though ' +
+ 'My Way OverThere—see ' +
+ 'Smart Engine in that ' +
+ 'Smart Engine GUI
',
+ '[[With:Colon]]')
+ end
+
+ # TODO Remove the leading underscores from this test when upgrading to RedCloth 3.0.1;
+ # also add a test for the "Unhappy Face" problem (another interesting RedCloth bug)
+ def test_list_with_tildas
+ list_with_tildas = <<-EOL
+ * "a":~b
+ * c~ d
+ EOL
+
+ assert_markup_parsed_as(
+ "
',
+ @web.page("SecondPage").display_content)
+ end
+
+ def test_pages_by_revision
+ add_sample_pages
+ assert_equal 'EverBeenHated', @web.select.by_revision.first.name
+ end
+
+ def test_pages_by_match
+ add_sample_pages
+ assert_equal 2, @web.select { |page| page.content =~ /me/i }.length
+ assert_equal 1, @web.select { |page| page.content =~ /Who/i }.length
+ assert_equal 0, @web.select { |page| page.content =~ /none/i }.length
+ end
+
+ def test_references
+ add_sample_pages
+ assert_equal 1, @web.select.pages_that_reference('EverBeenHated').length
+ assert_equal 0, @web.select.pages_that_reference('EverBeenInLove').length
+ end
+
+ def test_delete
+ add_sample_pages
+ assert_equal 2, @web.pages.length
+ @web.remove_pages([ @web.page('EverBeenInLove') ])
+ assert_equal 1, @web.pages(true).length
+ end
+
+ def test_make_link
+ add_sample_pages
+
+ existing_page_wiki_url =
+ 'Ever Been In Love'
+ existing_page_published_url =
+ 'Ever Been In Love'
+ existing_page_static_url =
+ 'Ever Been In Love'
+ new_page_wiki_url =
+ 'Unknown Word?'
+ new_page_published_url =
+ new_page_static_url =
+ 'Unknown Word'
+
+ # no options
+ assert_equal existing_page_wiki_url, @web.make_link('EverBeenInLove')
+
+ # :mode => :export
+ assert_equal existing_page_static_url, @web.make_link('EverBeenInLove', nil, :mode => :export)
+
+ # :mode => :publish
+ assert_equal existing_page_published_url,
+ @web.make_link('EverBeenInLove', nil, :mode => :publish)
+
+ # new page, no options
+ assert_equal new_page_wiki_url, @web.make_link('UnknownWord')
+
+ # new page, :mode => :export
+ assert_equal new_page_static_url, @web.make_link('UnknownWord', nil, :mode => :export)
+
+ # new page, :mode => :publish
+ assert_equal new_page_published_url, @web.make_link('UnknownWord', nil, :mode => :publish)
+
+ # Escaping special characters in the name
+ assert_equal(
+ 'Smith & Wesson?',
+ @web.make_link('Smith & Wesson'))
+
+ # optionally using text as the link text
+ assert_equal(
+ existing_page_published_url.sub(/>Ever Been In Love, ">Haven't you ever been in love?<"),
+ @web.make_link('EverBeenInLove', "Haven't you ever been in love?", :mode => :publish))
+
+ end
+
+ def test_initialize
+ web = Web.new(:name => 'Wiki2', :address => 'wiki2', :password => '123')
+
+ assert_equal 'Wiki2', web.name
+ assert_equal 'wiki2', web.address
+ assert_equal '123', web.password
+
+ # new web should be set for maximum features enabled
+ assert_equal :textile, web.markup
+ assert_equal '008B26', web.color
+ assert !web.safe_mode?
+ assert_equal([], web.pages)
+ assert web.allow_uploads?
+ assert_nil web.additional_style
+ assert !web.published?
+ assert !web.brackets_only?
+ assert !web.count_pages?
+ assert_equal 100, web.max_upload_size
+ end
+
+ def test_initialize_invalid_name
+ assert_raises(Instiki::ValidationError) {
+ Web.create(:name => 'Wiki2', :address => "wiki\234", :password => '123')
+ }
+ end
+
+ def test_new_page_linked_from_mother_page
+ # this was a bug in revision 204
+ home = @web.add_page('HomePage', 'This page refers to AnotherPage',
+ Time.local(2004, 4, 4, 16, 50), 'Alexey Verkhovsky')
+ @web.add_page('AnotherPage', 'This is \AnotherPage',
+ Time.local(2004, 4, 4, 16, 51), 'Alexey Verkhovsky')
+
+ @web.pages(true)
+ assert_equal [home], @web.select.pages_that_link_to('AnotherPage')
+ end
+
+ def test_orphaned_pages
+ add_sample_pages
+ home = @web.add_page('HomePage',
+ 'This is a home page, it should not be an orphan',
+ Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
+ author = @web.add_page('AlexeyVerkhovsky',
+ 'This is an author page, it should not be an orphan',
+ Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
+ self_linked = @web.add_page('SelfLinked',
+ 'I am me SelfLinked and link to EverBeenInLove',
+ Time.local(2004, 4, 4, 16, 50), 'AnonymousCoward')
+
+ # page that links to itself, and nobody else links to it must be an orphan
+ assert_equal ['EverBeenHated', 'SelfLinked'],
+ @web.select.orphaned_pages.collect{ |page| page.name }.sort
+ end
+
+ private
+
+ def add_sample_pages
+ @in_love = @web.add_page('EverBeenInLove', 'Who am I me',
+ Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
+ @hated = @web.add_page('EverBeenHated', 'I am me EverBeenHated',
+ Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson')
+ end
end
diff --git a/test/unit/wiki_words_test.rb b/test/unit/wiki_words_test.rb
index a1aa1ff9..93bc5d12 100755
--- a/test/unit/wiki_words_test.rb
+++ b/test/unit/wiki_words_test.rb
@@ -1,6 +1,6 @@
-#!/bin/env ruby -w
+#!/bin/env ruby
-require File.dirname(__FILE__) + '/../test_helper'
+require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
require 'wiki_words'
class WikiWordsTest < Test::Unit::TestCase
From 6832b2edf9edde74819c562eb1265a938d12f7f3 Mon Sep 17 00:00:00 2001
From: Rick Okin
Date: Tue, 9 Aug 2005 02:20:50 +0000
Subject: [PATCH 13/84] removed old models'
---
app/models-old/author.rb | 4 -
app/models-old/chunks/category.rb | 33 -----
app/models-old/chunks/chunk.rb | 86 -----------
app/models-old/chunks/engines.rb | 61 --------
app/models-old/chunks/include.rb | 41 ------
app/models-old/chunks/literal.rb | 31 ----
app/models-old/chunks/nowiki.rb | 28 ----
app/models-old/chunks/test.rb | 18 ---
app/models-old/chunks/uri.rb | 182 ------------------------
app/models-old/chunks/wiki.rb | 141 ------------------
app/models-old/file_yard.rb | 58 --------
app/models-old/page.rb | 120 ----------------
app/models-old/page_lock.rb | 23 ---
app/models-old/page_set.rb | 89 ------------
app/models-old/revision.rb | 127 -----------------
app/models-old/web.rb | 184 ------------------------
app/models-old/wiki_content.rb | 205 --------------------------
app/models-old/wiki_service.rb | 229 ------------------------------
app/models-old/wiki_words.rb | 23 ---
19 files changed, 1683 deletions(-)
delete mode 100644 app/models-old/author.rb
delete mode 100644 app/models-old/chunks/category.rb
delete mode 100644 app/models-old/chunks/chunk.rb
delete mode 100644 app/models-old/chunks/engines.rb
delete mode 100644 app/models-old/chunks/include.rb
delete mode 100644 app/models-old/chunks/literal.rb
delete mode 100644 app/models-old/chunks/nowiki.rb
delete mode 100644 app/models-old/chunks/test.rb
delete mode 100644 app/models-old/chunks/uri.rb
delete mode 100644 app/models-old/chunks/wiki.rb
delete mode 100644 app/models-old/file_yard.rb
delete mode 100644 app/models-old/page.rb
delete mode 100644 app/models-old/page_lock.rb
delete mode 100644 app/models-old/page_set.rb
delete mode 100644 app/models-old/revision.rb
delete mode 100644 app/models-old/web.rb
delete mode 100644 app/models-old/wiki_content.rb
delete mode 100644 app/models-old/wiki_service.rb
delete mode 100644 app/models-old/wiki_words.rb
diff --git a/app/models-old/author.rb b/app/models-old/author.rb
deleted file mode 100644
index 258cc2b8..00000000
--- a/app/models-old/author.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-class Author < String
- attr_accessor :ip
- def initialize(name, ip) @ip = ip; super(name) end
-end
\ No newline at end of file
diff --git a/app/models-old/chunks/category.rb b/app/models-old/chunks/category.rb
deleted file mode 100644
index d08d8636..00000000
--- a/app/models-old/chunks/category.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require 'chunks/chunk'
-
-# The category chunk looks for "category: news" on a line by
-# itself and parses the terms after the ':' as categories.
-# Other classes can search for Category chunks within
-# rendered content to find out what categories this page
-# should be in.
-#
-# Category lines can be hidden using ':category: news', for example
-class Category < Chunk::Abstract
- CATEGORY_PATTERN = /^(:)?category\s*:(.*)$/i
- def self.pattern() CATEGORY_PATTERN end
-
- attr_reader :hidden, :list
-
-def initialize(match_data, content)
- super(match_data, content)
- @hidden = match_data[1]
- @list = match_data[2].split(',').map { |c| c.strip }
- @unmask_text = ''
- if @hidden
- @unmask_text = ''
- else
- category_urls = @list.map { |category| url(category) }.join(', ')
- @unmask_text = '
category: ' + category_urls + '
'
- end
- end
-
- # TODO move presentation of page metadata to controller/view
- def url(category)
- %{#{category}}
- end
-end
diff --git a/app/models-old/chunks/chunk.rb b/app/models-old/chunks/chunk.rb
deleted file mode 100644
index 9ba3cc04..00000000
--- a/app/models-old/chunks/chunk.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-require 'uri/common'
-
-# A chunk is a pattern of text that can be protected
-# and interrogated by a renderer. Each Chunk class has a
-# +pattern+ that states what sort of text it matches.
-# Chunks are initalized by passing in the result of a
-# match by its pattern.
-
-module Chunk
- class Abstract
-
- # automatically construct the array of derivatives of Chunk::Abstract
- @derivatives = []
-
- class << self
- attr_reader :derivatives
- end
-
- def self::inherited( klass )
- Abstract::derivatives << klass
- end
-
- # the class name part of the mask strings
- def self.mask_string
- self.to_s.delete(':').downcase
- end
-
- # a regexp that matches all chunk_types masks
- def Abstract::mask_re(chunk_types)
- tmp = chunk_types.map{|klass| klass.mask_string}.join("|")
- Regexp.new("chunk([0-9a-f]+n\\d+)(#{tmp})chunk")
- end
-
- attr_reader :text, :unmask_text, :unmask_mode
-
- def initialize(match_data, content)
- @text = match_data[0]
- @content = content
- @unmask_mode = :normal
- end
-
- # Find all the chunks of the given type in content
- # Each time the pattern is matched, create a new
- # chunk for it, and replace the occurance of the chunk
- # in this content with its mask.
- def self.apply_to(content)
- content.gsub!( self.pattern ) do |match|
- new_chunk = self.new($~, content)
- content.add_chunk(new_chunk)
- new_chunk.mask
- end
- end
-
- # should contain only [a-z0-9]
- def mask
- @mask ||="chunk#{@id}#{self.class.mask_string}chunk"
- end
-
- # We should not use object_id because object_id is not guarantied
- # to be unique when we restart the wiki (new object ids can equal old ones
- # that were restored from madeleine storage)
- def id
- @id ||= "#{@content.page_id}n#{@content.chunk_id}"
- end
-
- def unmask
- @content.sub!(mask, @unmask_text)
- end
-
- def rendered?
- @unmask_mode == :normal
- end
-
- def escaped?
- @unmask_mode == :escape
- end
-
- def revert
- @content.sub!(mask, @text)
- # unregister
- @content.delete_chunk(self)
- end
-
- end
-
-end
diff --git a/app/models-old/chunks/engines.rb b/app/models-old/chunks/engines.rb
deleted file mode 100644
index fe5a96a8..00000000
--- a/app/models-old/chunks/engines.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-$: << File.dirname(__FILE__) + "../../lib"
-
-require 'redcloth'
-require 'bluecloth_tweaked'
-require 'rdocsupport'
-require 'chunks/chunk'
-
-# The markup engines are Chunks that call the one of RedCloth
-# or RDoc to convert text. This markup occurs when the chunk is required
-# to mask itself.
-module Engines
- class AbstractEngine < Chunk::Abstract
-
- # Create a new chunk for the whole content and replace it with its mask.
- def self.apply_to(content)
- new_chunk = self.new(content)
- content.replace(new_chunk.mask)
- end
-
- private
-
- # Never create engines by constructor - use apply_to instead
- def initialize(content)
- @content = content
- end
-
- end
-
- class Textile < AbstractEngine
- def mask
- redcloth = RedCloth.new(@content, [:hard_breaks] + @content.options[:engine_opts])
- redcloth.filter_html = false
- redcloth.no_span_caps = false
- redcloth.to_html(:textile)
- end
- end
-
- class Markdown < AbstractEngine
- def mask
- BlueCloth.new(@content, @content.options[:engine_opts]).to_html
- end
- end
-
- class Mixed < AbstractEngine
- def mask
- redcloth = RedCloth.new(@content, @content.options[:engine_opts])
- redcloth.filter_html = false
- redcloth.no_span_caps = false
- redcloth.to_html
- end
- end
-
- class RDoc < AbstractEngine
- def mask
- RDocSupport::RDocFormatter.new(@content).to_html
- end
- end
-
- MAP = { :textile => Textile, :markdown => Markdown, :mixed => Mixed, :rdoc => RDoc }
- MAP.default = Textile
-end
diff --git a/app/models-old/chunks/include.rb b/app/models-old/chunks/include.rb
deleted file mode 100644
index 370093cc..00000000
--- a/app/models-old/chunks/include.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-require 'chunks/wiki'
-
-# Includes the contents of another page for rendering.
-# The include command looks like this: "[[!include PageName]]".
-# It is a WikiReference since it refers to another page (PageName)
-# and the wiki content using this command must be notified
-# of changes to that page.
-# If the included page could not be found, a warning is displayed.
-
-class Include < WikiChunk::WikiReference
-
- INCLUDE_PATTERN = /\[\[!include\s+(.*?)\]\]\s*/i
- def self.pattern() INCLUDE_PATTERN end
-
-
- def initialize(match_data, content)
- super
- @page_name = match_data[1].strip
- @unmask_text = get_unmask_text_avoiding_recursion_loops
- end
-
- private
-
- def get_unmask_text_avoiding_recursion_loops
- if refpage then
- refpage.clear_display_cache
- if refpage.wiki_includes.include?(@content.page_name)
- # this will break the recursion
- @content.delete_chunk(self)
- return "Recursive include detected; #{@page_name} --> #{@content.page_name} " +
- "--> #{@page_name}\n"
- else
- @content.merge_chunks(refpage.display_content)
- return refpage.display_content.pre_rendered
- end
- else
- return "Could not include #{@page_name}\n"
- end
- end
-
-end
diff --git a/app/models-old/chunks/literal.rb b/app/models-old/chunks/literal.rb
deleted file mode 100644
index 09da4005..00000000
--- a/app/models-old/chunks/literal.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-require 'chunks/chunk'
-
-# These are basic chunks that have a pattern and can be protected.
-# They are used by rendering process to prevent wiki rendering
-# occuring within literal areas such as and
blocks
-# and within HTML tags.
-module Literal
-
- class AbstractLiteral < Chunk::Abstract
-
- def initialize(match_data, content)
- super
- @unmask_text = @text
- end
-
- end
-
- # A literal chunk that protects 'code' and 'pre' tags from wiki rendering.
- class Pre < AbstractLiteral
- PRE_BLOCKS = "a|pre|code"
- PRE_PATTERN = Regexp.new('<('+PRE_BLOCKS+')\b[^>]*?>.*?\1>', Regexp::MULTILINE)
- def self.pattern() PRE_PATTERN end
- end
-
- # A literal chunk that protects HTML tags from wiki rendering.
- class Tags < AbstractLiteral
- TAGS = "a|img|em|strong|div|span|table|td|th|ul|ol|li|dl|dt|dd"
- TAGS_PATTERN = Regexp.new('<(?:'+TAGS+')[^>]*?>', Regexp::MULTILINE)
- def self.pattern() TAGS_PATTERN end
- end
-end
diff --git a/app/models-old/chunks/nowiki.rb b/app/models-old/chunks/nowiki.rb
deleted file mode 100644
index ef99ec0b..00000000
--- a/app/models-old/chunks/nowiki.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-require 'chunks/chunk'
-
-# This chunks allows certain parts of a wiki page to be hidden from the
-# rest of the rendering pipeline. It should be run at the beginning
-# of the pipeline in `wiki_content.rb`.
-#
-# An example use of this chunk is to markup double brackets or
-# auto URI links:
-# Here are [[double brackets]] and a URI: www.uri.org
-#
-# The contents of the chunks will not be processed by any other chunk
-# so the `www.uri.org` and the double brackets will appear verbatim.
-#
-# Author: Mark Reid
-# Created: 8th June 2004
-class NoWiki < Chunk::Abstract
-
- NOWIKI_PATTERN = Regexp.new('(.*?)', Regexp::MULTILINE)
- def self.pattern() NOWIKI_PATTERN end
-
- attr_reader :plain_text
-
- def initialize(match_data, content)
- super
- @plain_text = @unmask_text = match_data[1]
- end
-
-end
diff --git a/app/models-old/chunks/test.rb b/app/models-old/chunks/test.rb
deleted file mode 100644
index edf77d14..00000000
--- a/app/models-old/chunks/test.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require 'test/unit'
-
-class ChunkTest < Test::Unit::TestCase
-
- # Asserts a number of tests for the given type and text.
- def match(type, test_text, expected)
- pattern = type.pattern
- assert_match(pattern, test_text)
- pattern =~ test_text # Previous assertion guarantees match
- chunk = type.new($~)
-
- # Test if requested parts are correct.
- for method_sym, value in expected do
- assert_respond_to(chunk, method_sym)
- assert_equal(value, chunk.method(method_sym).call, "Checking value of '#{method_sym}'")
- end
- end
-end
diff --git a/app/models-old/chunks/uri.rb b/app/models-old/chunks/uri.rb
deleted file mode 100644
index 1a208535..00000000
--- a/app/models-old/chunks/uri.rb
+++ /dev/null
@@ -1,182 +0,0 @@
-require 'chunks/chunk'
-
-# This wiki chunk matches arbitrary URIs, using patterns from the Ruby URI modules.
-# It parses out a variety of fields that could be used by renderers to format
-# the links in various ways (shortening domain names, hiding email addresses)
-# It matches email addresses and host.com.au domains without schemes (http://)
-# but adds these on as required.
-#
-# The heuristic used to match a URI is designed to err on the side of caution.
-# That is, it is more likely to not autolink a URI than it is to accidently
-# autolink something that is not a URI. The reason behind this is it is easier
-# to force a URI link by prefixing 'http://' to it than it is to escape and
-# incorrectly marked up non-URI.
-#
-# I'm using a part of the [ISO 3166-1 Standard][iso3166] for country name suffixes.
-# The generic names are from www.bnoack.com/data/countrycode2.html)
-# [iso3166]: http://geotags.com/iso3166/
-
-class URIChunk < Chunk::Abstract
- include URI::REGEXP::PATTERN
-
- # this condition is to get rid of pesky warnings in tests
- unless defined? URIChunk::INTERNET_URI_REGEXP
-
- GENERIC = 'aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org'
-
- COUNTRY = 'ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|' +
- 'bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cf|cd|cg|ch|ci|ck|cl|' +
- 'cm|cn|co|cr|cs|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|fi|' +
- 'fj|fk|fm|fo|fr|fx|ga|gb|gd|ge|gf|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|' +
- 'hk|hm|hn|hr|ht|hu|id|ie|il|in|io|iq|ir|is|it|jm|jo|jp|ke|kg|kh|ki|km|kn|' +
- 'kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|' +
- 'mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nt|' +
- 'nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|' +
- 'sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|' +
- 'tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|' +
- 'ws|ye|yt|yu|za|zm|zr|zw'
- # These are needed otherwise HOST will match almost anything
- TLDS = "(?:#{GENERIC}|#{COUNTRY})"
-
- # Redefine USERINFO so that it must have non-zero length
- USERINFO = "(?:[#{UNRESERVED};:&=+$,]|#{ESCAPED})+"
-
- # unreserved_no_ending = alphanum | mark, but URI_ENDING [)!] excluded
- UNRESERVED_NO_ENDING = "-_.~*'(#{ALNUM}"
-
- # this ensures that query or fragment do not end with URI_ENDING
- # and enable us to use a much simpler self.pattern Regexp
-
- # uric_no_ending = reserved | unreserved_no_ending | escaped
- URIC_NO_ENDING = "(?:[#{UNRESERVED_NO_ENDING}#{RESERVED}]|#{ESCAPED})"
- # query = *uric
- QUERY = "#{URIC_NO_ENDING}*"
- # fragment = *uric
- FRAGMENT = "#{URIC_NO_ENDING}*"
-
- # DOMLABEL is defined in the ruby uri library, TLDS is defined above
- INTERNET_HOSTNAME = "(?:#{DOMLABEL}\\.)+#{TLDS}"
-
- # Correct a typo bug in ruby 1.8.x lib/uri/common.rb
- PORT = '\\d*'
-
- INTERNET_URI =
- "(?:(#{SCHEME}):/{0,2})?" + # Optional scheme: (\1)
- "(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2)
- "(#{INTERNET_HOSTNAME})" + # Mandatory hostname (\3)
- "(?::(#{PORT}))?" + # Optional :port (\4)
- "(#{ABS_PATH})?" + # Optional absolute path (\5)
- "(?:\\?(#{QUERY}))?" + # Optional ?query (\6)
- "(?:\\#(#{FRAGMENT}))?" + # Optional #fragment (\7)
- '(?=\.?(?:\s|\)|\z))' # ends only with optional dot + space or ")"
- # or end of the string
-
- SUSPICIOUS_PRECEDING_CHARACTER = '(!|\"\:|\"|\\\'|\]\()?' # any of !, ":, ", ', ](
-
- INTERNET_URI_REGEXP =
- Regexp.new(SUSPICIOUS_PRECEDING_CHARACTER + INTERNET_URI, Regexp::EXTENDED, 'N')
-
- end
-
- def URIChunk.pattern
- INTERNET_URI_REGEXP
- end
-
- attr_reader :user, :host, :port, :path, :query, :fragment, :link_text
-
- def self.apply_to(content)
- content.gsub!( self.pattern ) do |matched_text|
- chunk = self.new($~, content)
- if chunk.avoid_autolinking?
- # do not substitute nor register the chunk
- matched_text
- else
- content.add_chunk(chunk)
- chunk.mask
- end
- end
- end
-
- def initialize(match_data, content)
- super
- @link_text = match_data[0]
- @suspicious_preceding_character = match_data[1]
- @original_scheme, @user, @host, @port, @path, @query, @fragment = match_data[2..-1]
- treat_trailing_character
- @unmask_text = "#{link_text}"
- end
-
- def avoid_autolinking?
- not @suspicious_preceding_character.nil?
- end
-
- def treat_trailing_character
- # If the last character matched by URI pattern is in ! or ), this may be part of the markup,
- # not a URL. We should handle it as such. It is possible to do it by a regexp, but
- # much easier to do programmatically
- last_char = @link_text[-1..-1]
- if last_char == ')' or last_char == '!'
- @trailing_punctuation = last_char
- @link_text.chop!
- [@original_scheme, @user, @host, @port, @path, @query, @fragment].compact.last.chop!
- else
- @trailing_punctuation = nil
- end
- end
-
- def scheme
- @original_scheme or (@user ? 'mailto' : 'http')
- end
-
- def scheme_delimiter
- scheme == 'mailto' ? ':' : '://'
- end
-
- def user_delimiter
- '@' unless @user.nil?
- end
-
- def port_delimiter
- ':' unless @port.nil?
- end
-
- def query_delimiter
- '?' unless @query.nil?
- end
-
- def uri
- [scheme, scheme_delimiter, user, user_delimiter, host, port_delimiter, port, path,
- query_delimiter, query].compact.join
- end
-
-end
-
-# uri with mandatory scheme but less restrictive hostname, like
-# http://localhost:2500/blah.html
-class LocalURIChunk < URIChunk
-
- unless defined? LocalURIChunk::LOCAL_URI_REGEXP
- # hostname can be just a simple word like 'localhost'
- ANY_HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?"
-
- # The basic URI expression as a string
- # Scheme and hostname are mandatory
- LOCAL_URI =
- "(?:(#{SCHEME})://)+" + # Mandatory scheme:// (\1)
- "(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2)
- "(#{ANY_HOSTNAME})" + # Mandatory hostname (\3)
- "(?::(#{PORT}))?" + # Optional :port (\4)
- "(#{ABS_PATH})?" + # Optional absolute path (\5)
- "(?:\\?(#{QUERY}))?" + # Optional ?query (\6)
- "(?:\\#(#{FRAGMENT}))?" + # Optional #fragment (\7)
- '(?=\.?(?:\s|\)|\z))' # ends only with optional dot + space or ")"
- # or end of the string
-
- LOCAL_URI_REGEXP = Regexp.new(SUSPICIOUS_PRECEDING_CHARACTER + LOCAL_URI, Regexp::EXTENDED, 'N')
- end
-
- def LocalURIChunk.pattern
- LOCAL_URI_REGEXP
- end
-
-end
diff --git a/app/models-old/chunks/wiki.rb b/app/models-old/chunks/wiki.rb
deleted file mode 100644
index 840f644a..00000000
--- a/app/models-old/chunks/wiki.rb
+++ /dev/null
@@ -1,141 +0,0 @@
-require 'wiki_words'
-require 'chunks/chunk'
-require 'chunks/wiki'
-require 'cgi'
-
-# Contains all the methods for finding and replacing wiki related links.
-module WikiChunk
- include Chunk
-
- # A wiki reference is the top-level class for anything that refers to
- # another wiki page.
- class WikiReference < Chunk::Abstract
-
- # Name of the referenced page
- attr_reader :page_name
-
- # the referenced page
- def refpage
- @content.web.pages[@page_name]
- end
-
- end
-
- # A wiki link is the top-level class for links that refers to
- # another wiki page.
- class WikiLink < WikiReference
-
- attr_reader :link_text, :link_type
-
- def initialize(match_data, content)
- super
- @link_type = :show
- end
-
- def self.apply_to(content)
- content.gsub!( self.pattern ) do |matched_text|
- chunk = self.new($~, content)
- if chunk.textile_url?
- # do not substitute
- matched_text
- else
- content.add_chunk(chunk)
- chunk.mask
- end
- end
- end
-
- # the referenced page
- def refpage
- @content.web.pages[@page_name]
- end
-
- def textile_url?
- not @textile_link_suffix.nil?
- end
-
- end
-
- # This chunk matches a WikiWord. WikiWords can be escaped
- # by prepending a '\'. When this is the case, the +escaped_text+
- # method will return the WikiWord instead of the usual +nil+.
- # The +page_name+ method returns the matched WikiWord.
- class Word < WikiLink
-
- attr_reader :escaped_text
-
- unless defined? WIKI_WORD
- WIKI_WORD = Regexp.new('(":)?(\\\\)?(' + WikiWords::WIKI_WORD_PATTERN + ')\b', 0, "utf-8")
- end
-
- def self.pattern
- WIKI_WORD
- end
-
- def initialize(match_data, content)
- super
- @textile_link_suffix, @escape, @page_name = match_data[1..3]
- if @escape
- @unmask_mode = :escape
- @escaped_text = @page_name
- else
- @escaped_text = nil
- end
- @link_text = WikiWords.separate(@page_name)
- @unmask_text = (@escaped_text || @content.page_link(@page_name, @link_text, @link_type))
- end
-
- end
-
- # This chunk handles [[bracketted wiki words]] and
- # [[AliasedWords|aliased wiki words]]. The first part of an
- # aliased wiki word must be a WikiWord. If the WikiWord
- # is aliased, the +link_text+ field will contain the
- # alias, otherwise +link_text+ will contain the entire
- # contents within the double brackets.
- #
- # NOTE: This chunk must be tested before WikiWord since
- # a WikiWords can be a substring of a WikiLink.
- class Link < WikiLink
-
- unless defined? WIKI_LINK
- WIKI_LINK = /(":)?\[\[\s*([^\]\s][^\]]+?)\s*\]\]/
- LINK_TYPE_SEPARATION = Regexp.new('^(.+):((file)|(pic))$', 0, 'utf-8')
- ALIAS_SEPARATION = Regexp.new('^(.+)\|(.+)$', 0, 'utf-8')
- end
-
- def self.pattern() WIKI_LINK end
-
- def initialize(match_data, content)
- super
- @textile_link_suffix, @page_name = match_data[1..2]
- @link_text = @page_name
- separate_link_type
- separate_alias
- @unmask_text = @content.page_link(@page_name, @link_text, @link_type)
- end
-
- private
-
- # if link wihin the brackets has a form of [[filename:file]] or [[filename:pic]],
- # this means a link to a picture or a file
- def separate_link_type
- link_type_match = LINK_TYPE_SEPARATION.match(@page_name)
- if link_type_match
- @link_text = @page_name = link_type_match[1]
- @link_type = link_type_match[2..3].compact[0].to_sym
- end
- end
-
- # link text may be different from page name. this will look like [[actual page|link text]]
- def separate_alias
- alias_match = ALIAS_SEPARATION.match(@page_name)
- if alias_match
- @page_name, @link_text = alias_match[1..2]
- end
- # note that [[filename|link text:file]] is also supported
- end
-
- end
-
-end
diff --git a/app/models-old/file_yard.rb b/app/models-old/file_yard.rb
deleted file mode 100644
index b35dda2e..00000000
--- a/app/models-old/file_yard.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-require 'fileutils'
-require 'instiki_errors'
-
-class FileYard
-
- attr_reader :files_path
-
- def initialize(files_path, max_upload_size)
- @files_path, @max_upload_size = files_path, max_upload_size
- FileUtils.mkdir_p(@files_path) unless File.exist?(@files_path)
- @files = Dir["#{@files_path}/*"].collect{|path| File.basename(path) if File.file?(path) }.compact
- end
-
- def upload_file(name, io)
- sanitize_file_name(name)
- if io.kind_of?(Tempfile)
- io.close
- check_upload_size(io.size)
- File.chmod(600, file_path(name)) if File.exists? file_path(name)
- FileUtils.mv(io.path, file_path(name))
- else
- content = io.read
- check_upload_size(content.length)
- File.open(file_path(name), 'wb') { |f| f.write(content) }
- end
- # just in case, restrict read access and prohibit write access to the uploaded file
- FileUtils.chmod(0440, file_path(name))
- end
-
- def files
- Dir["#{files_path}/*"].collect{|path| File.basename(path) if File.file?(path)}.compact
- end
-
- def has_file?(name)
- files.include?(name)
- end
-
- def file_path(name)
- "#{files_path}/#{name}"
- end
-
- SANE_FILE_NAME = /[a-zA-Z0-9\-_\. ]{1,255}/
-
- def sanitize_file_name(name)
- unless name =~ SANE_FILE_NAME or name == '.' or name == '..'
- raise Instiki::ValidationError.new("Invalid file name: '#{name}'.\n" +
- "Only latin characters, digits, dots, underscores, dashes and spaces are accepted.")
- end
- end
-
- def check_upload_size(actual_upload_size)
- if actual_upload_size > @max_upload_size.kilobytes
- raise Instiki::ValidationError.new("Uploaded file size (#{actual_upload_size / 1024} " +
- "kbytes) exceeds the maximum (#{@max_upload_size} kbytes) set for this wiki")
- end
- end
-
-end
diff --git a/app/models-old/page.rb b/app/models-old/page.rb
deleted file mode 100644
index 5926fb85..00000000
--- a/app/models-old/page.rb
+++ /dev/null
@@ -1,120 +0,0 @@
-require 'date'
-require 'page_lock'
-require 'revision'
-require 'wiki_words'
-require 'chunks/wiki'
-
-class Page
- include PageLock
-
- attr_reader :name, :web
- attr_accessor :revisions
-
- def initialize(web, name)
- raise 'nil web' if web.nil?
- raise 'nil name' if name.nil?
- @web, @name, @revisions = web, name, []
- end
-
- def revise(content, created_at, author)
-
- if not @revisions.empty? and content == @revisions.last.content
- raise Instiki::ValidationError.new(
- "You have tried to save page '#{name}' without changing its content")
- end
-
- # Try to render content to make sure that markup engine can take it,
- # before addin a revision to the page
- Revision.new(self, @revisions.length, content, created_at, author).force_rendering
-
- # A user may change a page, look at it and make some more changes - several times.
- # Not to record every such iteration as a new revision, if the previous revision was done
- # by the same author, not more than 30 minutes ago, then update the last revision instead of
- # creating a new one
- if !@revisions.empty? && continous_revision?(created_at, author)
- @revisions.last.created_at = created_at
- @revisions.last.content = content
- @revisions.last.clear_display_cache
- else
- @revisions << Revision.new(self, @revisions.length, content, created_at, author)
- end
-
- self.revisions.last.force_rendering
- # at this point the page may not be inserted in the web yet, and therefore
- # references to the page itself are rendered as "unresolved". Clearing the cache allows
- # the page to re-render itself once again, hopefully _after_ it is inserted in the web
- self.revisions.last.clear_display_cache
-
- @web.refresh_pages_with_references(@name) if @revisions.length == 1
-
- self
-
- end
-
- def rollback(revision_number, created_at, author_ip = nil)
- roll_back_revision = @revisions[revision_number].dup
- revise(roll_back_revision.content, created_at, Author.new(roll_back_revision.author, author_ip))
- end
-
- def revisions?
- revisions.length > 1
- end
-
- def revised_on
- created_on
- end
-
- def in_category?(cat)
- cat.nil? || cat.empty? || categories.include?(cat)
- end
-
- def categories
- display_content.find_chunks(Category).map { |cat| cat.list }.flatten
- end
-
- def authors
- revisions.collect { |rev| rev.author }
- end
-
- def references
- @web.select.pages_that_reference(name)
- end
-
- def linked_from
- @web.select.pages_that_link_to(name)
- end
-
- def included_from
- @web.select.pages_that_include(name)
- end
-
- # Returns the original wiki-word name as separate words, so "MyPage" becomes "My Page".
- def plain_name
- @web.brackets_only ? name : WikiWords.separate(name)
- end
-
- # used to build chunk ids.
- def id
- @id ||= name.unpack('H*').first
- end
-
- def link(options = {})
- @web.make_link(name, nil, options)
- end
-
- def author_link(options = {})
- @web.make_link(author, nil, options)
- end
-
- private
-
- def continous_revision?(created_at, author)
- @revisions.last.author == author && @revisions.last.created_at + 30.minutes > created_at
- end
-
- # Forward method calls to the current revision, so the page responds to all revision calls
- def method_missing(method_symbol)
- revisions.last.send(method_symbol)
- end
-
-end
diff --git a/app/models-old/page_lock.rb b/app/models-old/page_lock.rb
deleted file mode 100644
index 276274e6..00000000
--- a/app/models-old/page_lock.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# Contains all the lock methods to be mixed in with the page
-module PageLock
- LOCKING_PERIOD = 30 * 60 # 30 minutes
-
- attr_reader :locked_by
-
- def lock(time, locked_by)
- @locked_at, @locked_by = time, locked_by
- end
-
- def lock_duration(time)
- ((time - @locked_at) / 60).to_i unless @locked_at.nil?
- end
-
- def unlock
- @locked_at = nil
- end
-
- def locked?(comparison_time)
- @locked_at + LOCKING_PERIOD > comparison_time unless @locked_at.nil?
- end
-
-end
\ No newline at end of file
diff --git a/app/models-old/page_set.rb b/app/models-old/page_set.rb
deleted file mode 100644
index 5b298ea6..00000000
--- a/app/models-old/page_set.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-# Container for a set of pages with methods for manipulation.
-
-class PageSet < Array
- attr_reader :web
-
- def initialize(web, pages = nil, condition = nil)
- @web = web
- # if pages is not specified, make a list of all pages in the web
- if pages.nil?
- super(web.pages.values)
- # otherwise use specified pages and condition to produce a set of pages
- elsif condition.nil?
- super(pages)
- else
- super(pages.select { |page| condition[page] })
- end
- end
-
- def most_recent_revision
- self.map { |page| page.created_at }.max || Time.at(0)
- end
-
-
- def by_name
- PageSet.new(@web, sort_by { |page| page.name })
- end
-
- alias :sort :by_name
-
- def by_revision
- PageSet.new(@web, sort_by { |page| page.created_at }).reverse
- end
-
- def pages_that_reference(page_name)
- self.select { |page| page.wiki_references.include?(page_name) }
- end
-
- def pages_that_link_to(page_name)
- self.select { |page| page.wiki_words.include?(page_name) }
- end
-
- def pages_that_include(page_name)
- self.select { |page| page.wiki_includes.include?(page_name) }
- end
-
- def pages_authored_by(author)
- self.select { |page| page.authors.include?(author) }
- end
-
- def characters
- self.inject(0) { |chars,page| chars += page.content.size }
- end
-
- # Returns all the orphaned pages in this page set. That is,
- # pages in this set for which there is no reference in the web.
- # The HomePage and author pages are always assumed to have
- # references and so cannot be orphans
- # Pages that refer to themselves and have no links from outside are oprphans.
- def orphaned_pages
- never_orphans = web.select.authors + ['HomePage']
- self.select { |page|
- if never_orphans.include? page.name
- false
- else
- references = pages_that_reference(page.name)
- references.empty? or references == [page]
- end
- }
- end
-
- # Returns all the wiki words in this page set for which
- # there are no pages in this page set's web
- def wanted_pages
- wiki_words - web.select.names
- end
-
- def names
- self.map { |page| page.name }
- end
-
- def wiki_words
- self.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
- end
-
- def authors
- self.inject([]) { |authors, page| authors << page.authors }.flatten.uniq.sort
- end
-
-end
diff --git a/app/models-old/revision.rb b/app/models-old/revision.rb
deleted file mode 100644
index c5f0eb8a..00000000
--- a/app/models-old/revision.rb
+++ /dev/null
@@ -1,127 +0,0 @@
-require 'diff'
-require 'wiki_content'
-require 'chunks/wiki'
-require 'date'
-require 'author'
-require 'page'
-
-class Revision
-
- attr_accessor :page, :number, :content, :created_at, :author
-
- def initialize(page, number, content, created_at, author)
- @page, @number, @created_at, @author = page, number, created_at, author
- self.content = content
- @display_cache = nil
- end
-
- def created_on
- Date.new(@created_at.year, @created_at.mon, @created_at.day)
- end
-
- def pretty_created_at
- # Must use DateTime because Time doesn't support %e on at least some platforms
- DateTime.new(
- @created_at.year, @created_at.mon, @created_at.day, @created_at.hour, @created_at.min
- ).strftime "%B %e, %Y %H:%M"
- end
-
-
-# todo: drop next_revision, previuous_revision and number from here - unused code
- def next_revision
- page.revisions[number + 1]
- end
-
- def previous_revision
- number > 0 ? page.revisions[number - 1] : nil
- end
-
- # Returns an array of all the WikiIncludes present in the content of this revision.
- def wiki_includes
- unless @wiki_includes_cache
- chunks = display_content.find_chunks(Include)
- @wiki_includes_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
- end
- @wiki_includes_cache
- end
-
- # Returns an array of all the WikiReferences present in the content of this revision.
- def wiki_references
- unless @wiki_references_cache
- chunks = display_content.find_chunks(WikiChunk::WikiReference)
- @wiki_references_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
- end
- @wiki_references_cache
- end
-
- # Returns an array of all the WikiWords present in the content of this revision.
- def wiki_words
- unless @wiki_words_cache
- wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
- @wiki_words_cache = wiki_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
- end
- @wiki_words_cache
- end
-
- # Returns an array of all the WikiWords present in the content of this revision.
- # that already exists as a page in the web.
- def existing_pages
- wiki_words.select { |wiki_word| page.web.pages[wiki_word] }
- end
-
- # Returns an array of all the WikiWords present in the content of this revision
- # that *doesn't* already exists as a page in the web.
- def unexisting_pages
- wiki_words - existing_pages
- end
-
- # Explicit check for new type of display cache with chunks_by_type method.
- # Ensures new version works with older snapshots.
- def display_content
- unless @display_cache && @display_cache.respond_to?(:chunks_by_type)
- @display_cache = WikiContent.new(self)
- @display_cache.render!
- end
- @display_cache
- end
-
- def display_diff
- previous_revision ? HTMLDiff.diff(previous_revision.display_content, display_content) : display_content
- end
-
- def clear_display_cache
- @wiki_words_cache = @published_cache = @display_cache = @wiki_includes_cache =
- @wiki_references_cache = nil
- end
-
- def display_published
- unless @published_cache && @published_cache.respond_to?(:chunks_by_type)
- @published_cache = WikiContent.new(self, {:mode => :publish})
- @published_cache.render!
- end
- @published_cache
- end
-
- def display_content_for_export
- WikiContent.new(self, {:mode => :export} ).render!
- end
-
- def force_rendering
- begin
- display_content.render!
- rescue => e
- ApplicationController.logger.error "Failed rendering page #{@name}"
- ApplicationController.logger.error e
- message = e.message
- # substitute content with an error message
- self.content = <<-EOL
-
Markup engine has failed to render this page, raising the following error:
-
#{message}
-
#{self.content}
- EOL
- clear_display_cache
- raise e
- end
- end
-
-end
diff --git a/app/models-old/web.rb b/app/models-old/web.rb
deleted file mode 100644
index 0e21fc80..00000000
--- a/app/models-old/web.rb
+++ /dev/null
@@ -1,184 +0,0 @@
-require 'cgi'
-require 'page'
-require 'page_set'
-require 'wiki_words'
-require 'zip/zip'
-
-class Web
- attr_accessor :name, :password, :safe_mode, :pages
- attr_accessor :additional_style, :allow_uploads, :published
- attr_reader :address
-
- # there are getters for all these attributes, too
- attr_writer :markup, :color, :brackets_only, :count_pages, :max_upload_size
-
- def initialize(parent_wiki, name, address, password = nil)
- self.address = address
- @wiki, @name, @password = parent_wiki, name, password
-
- set_compatible_defaults
-
- @pages = {}
- @allow_uploads = true
- @additional_style = nil
- @published = false
- @count_pages = false
- end
-
- # Explicitly sets value of some web attributes to defaults, unless they are already set
- def set_compatible_defaults
- @markup = markup()
- @color = color()
- @safe_mode = safe_mode()
- @brackets_only = brackets_only()
- @max_upload_size = max_upload_size()
- @wiki = wiki
- end
-
- # All below getters know their default values. This is necessary to ensure compatibility with
- # 0.9 storages, where they were not defined.
- def brackets_only() @brackets_only || false end
- def color() @color ||= '008B26' end
- def count_pages() @count_pages || false end
- def markup() @markup ||= :textile end
- def max_upload_size() @max_upload_size || 100; end
- def wiki() @wiki ||= WikiService.instance; end
-
- def add_page(name, content, created_at, author)
- page = Page.new(self, name)
- page.revise(content, created_at, author)
- @pages[page.name] = page
- end
-
- def address=(the_address)
- if the_address != CGI.escape(the_address)
- raise Instiki::ValidationError.new('Web name should contain only valid URI characters')
- end
- @address = the_address
- end
-
- def authors
- select.authors
- end
-
- def categories
- select.map { |page| page.categories }.flatten.uniq.sort
- end
-
- def has_page?(name)
- pages[name]
- end
-
- def has_file?(name)
- wiki.file_yard(self).has_file?(name)
- end
-
- def make_file_link(mode, name, text, base_url)
- link = CGI.escape(name)
- case mode
- when :export
- if has_file?(name) then "#{text}"
- else "#{text}" end
- when :publish
- if has_file?(name) then "#{text}"
- else "#{text}" end
- else
- if has_file?(name)
- "#{text}"
- else
- "#{text}?"
- end
- end
- end
-
- # Create a link for the given page name and link text based
- # on the render mode in options and whether the page exists
- # in the this web.
- # The links a relative, and will work only if displayed on another WikiPage.
- # It should not be used in menus, templates and such - instead, use link_to_page helper
- def make_link(name, text = nil, options = {})
- text = CGI.escapeHTML(text || WikiWords.separate(name))
- mode = options[:mode] || :show
- base_url = options[:base_url] || '..'
- link_type = options[:link_type] || :show
- case link_type.to_sym
- when :show
- make_page_link(mode, name, text, base_url)
- when :file
- make_file_link(mode, name, text, base_url)
- when :pic
- make_pic_link(mode, name, text, base_url)
- else
- raise "Unknown link type: #{link_type}"
- end
- end
-
- def make_page_link(mode, name, text, base_url)
- link = CGI.escape(name)
- case mode.to_sym
- when :export
- if has_page?(name) then %{#{text}}
- else %{#{text}} end
- when :publish
- if has_page?(name) then %{#{text}}
- else %{#{text}} end
- else
- if has_page?(name)
- %{#{text}}
- else
- %{#{text}?}
- end
- end
- end
-
- def make_pic_link(mode, name, text, base_url)
- link = CGI.escape(name)
- case mode.to_sym
- when :export
- if has_file?(name) then %{}
- else %{} end
- when :publish
- if has_file?(name) then %{}
- else %{#{text}} end
- else
- if has_file?(name) then %{}
- else %{#{text}?} end
- end
- end
-
- # Clears the display cache for all the pages with references to
- def refresh_pages_with_references(page_name)
- select.pages_that_reference(page_name).each { |page|
- page.revisions.each { |revision| revision.clear_display_cache }
- }
- end
-
- def refresh_revisions
- select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
- end
-
- def remove_pages(pages_to_be_removed)
- pages.delete_if { |page_name, page| pages_to_be_removed.include?(page) }
- end
-
- def revised_on
- select.most_recent_revision
- end
-
- def select(&condition)
- PageSet.new(self, @pages.values, condition)
- end
-
- private
-
- # Returns an array of all the wiki words in any current revision
- def wiki_words
- pages.values.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
- end
-
- # Returns an array of all the page names on this web
- def page_names
- pages.keys
- end
-
-end
diff --git a/app/models-old/wiki_content.rb b/app/models-old/wiki_content.rb
deleted file mode 100644
index 89cd8c45..00000000
--- a/app/models-old/wiki_content.rb
+++ /dev/null
@@ -1,205 +0,0 @@
-require 'cgi'
-require 'chunks/engines'
-require 'chunks/category'
-require 'chunks/include'
-require 'chunks/wiki'
-require 'chunks/literal'
-require 'chunks/uri'
-require 'chunks/nowiki'
-
-# Wiki content is just a string that can process itself with a chain of
-# actions. The actions can modify wiki content so that certain parts of
-# it are protected from being rendered by later actions.
-#
-# When wiki content is rendered, it can be interrogated to find out
-# which chunks were rendered. This means things like categories, wiki
-# links, can be determined.
-#
-# Exactly how wiki content is rendered is determined by a number of
-# settings that are optionally passed in to a constructor. The current
-# options are:
-# * :engine
-# => The structural markup engine to use (Textile, Markdown, RDoc)
-# * :engine_opts
-# => A list of options to pass to the markup engines (safe modes, etc)
-# * :pre_engine_actions
-# => A list of render actions or chunks to be processed before the
-# markup engine is applied. By default this is:
-# Category, Include, URIChunk, WikiChunk::Link, WikiChunk::Word
-# * :post_engine_actions
-# => A list of render actions or chunks to apply after the markup
-# engine. By default these are:
-# Literal::Pre, Literal::Tags
-# * :mode
-# => How should the content be rendered? For normal display (show),
-# publishing (:publish) or export (:export)?
-
-module ChunkManager
- attr_reader :chunks_by_type, :chunks_by_id, :chunks, :chunk_id
-
- ACTIVE_CHUNKS = [ NoWiki, Category, WikiChunk::Link, URIChunk, LocalURIChunk,
- WikiChunk::Word ]
-
- HIDE_CHUNKS = [ Literal::Pre, Literal::Tags ]
-
- MASK_RE = {
- ACTIVE_CHUNKS => Chunk::Abstract.mask_re(ACTIVE_CHUNKS),
- HIDE_CHUNKS => Chunk::Abstract.mask_re(HIDE_CHUNKS)
- }
-
- def init_chunk_manager
- @chunks_by_type = Hash.new
- Chunk::Abstract::derivatives.each{|chunk_type|
- @chunks_by_type[chunk_type] = Array.new
- }
- @chunks_by_id = Hash.new
- @chunks = []
- @chunk_id = 0
- end
-
- def add_chunk(c)
- @chunks_by_type[c.class] << c
- @chunks_by_id[c.id] = c
- @chunks << c
- @chunk_id += 1
- end
-
- def delete_chunk(c)
- @chunks_by_type[c.class].delete(c)
- @chunks_by_id.delete(c.id)
- @chunks.delete(c)
- end
-
- def merge_chunks(other)
- other.chunks.each{|c| add_chunk(c)}
- end
-
- def scan_chunkid(text)
- text.scan(MASK_RE[ACTIVE_CHUNKS]){|a| yield a[0] }
- end
-
- def find_chunks(chunk_type)
- @chunks.select { |chunk| chunk.kind_of?(chunk_type) and chunk.rendered? }
- end
-
- # for testing and WikiContentStub; we need a page_id even if we have no page
- def page_id
- 0
- end
-
-end
-
-# A simplified version of WikiContent. Useful to avoid recursion problems in
-# WikiContent.new
-class WikiContentStub < String
- attr_reader :options
- include ChunkManager
- def initialize(content, options)
- super(content)
- @options = options
- init_chunk_manager
- end
-
- # Detects the mask strings contained in the text of chunks of type chunk_types
- # and yields the corresponding chunk ids
- # example: content = "chunk123categorychunk
This is a summary of the design rules your application has to
-follow to work with Madeleine.
-
-
-
The Prevalent System
-
-
Your objects have to fit into memory
-
-
All of them. At the same time.
-
-
Your objects have to be marshallable
-
-
Snapshots are taken of the system by marshalling the whole system to a
-file. If your classes can't be marshalled/unmarshalled then Madeleine
-won't be able to store/restore the system.
-
-
Your objects have to be deterministic
-
-
Deterministic means that, given the same commands, they have
-to always give the same results.
-
-
For the much of your code this won't
-be a problem, but there are a few common issues:
-
-
The system clock
-
You can't use the system clock (see instead ClockedSystem and TimeActor).
-
-
Random numbers
-
Kernel.rand() uses the system clock internally by
-default. Use Kernel.srand() to seed the random number
-generator before using rand().
-
-
Files, network and other IO
-
You generally can't access the outside world from within your
-prevalent system. Instead do IO outside of the prevalent system and
-call into the system when needed.
-
-
Changes to the system have to be done through command
-objects
-
-
Everything that modifies the prevalent system must be done through a
-command object sent to the Madeleine instance, using
-execute_command(aCommand). Queries that don't modify the
-system can be done either through direct method calls or through
-command objects.
-
-
Command Objects
-
-
A command object is an object that implements the method
-execute(system). They are an example of the "Command"
-design pattern.
-
-
The command objects also have to be marshallable
-
-
Madeleine keeps track of changes between snapshots by logging
-marshalled commands.
-
-
The command must raise errors before modifying the system
-
-
Unlike a RDBMS, Madeleine can't roll back a command (yet). This means
-that your commands will have to do their error checking and raise any
-errors before modifying the system. Failing to do this will cause an
-inconsistent command log.
-
-
Command objects can't hold references to the system's objects
-
-
Unmarshalling such a command would create clones of the original
-objects, which would then be modified instead of the real
-objects. The commands must find the objects to modify.
-
-
-
-$Id: designRules.html,v 1.1 2005/01/07 23:03:27 alexeyv Exp $
-
-
-
diff --git a/vendor/madeleine-0.7.1/docs/docs.css b/vendor/madeleine-0.7.1/docs/docs.css
deleted file mode 100755
index 0c70ccde..00000000
--- a/vendor/madeleine-0.7.1/docs/docs.css
+++ /dev/null
@@ -1,28 +0,0 @@
-body {
- background-color: #FFFFF0;
-}
-p {
- width: 70ex
-}
-h1 {
- font-family: verdana,arial,helvetica,sans-serif;
-}
-h2 {
- font-family: verdana,arial,helvetica,sans-serif;
- background: #EEEEE0;
-}
-h3 {
- font-family: verdana,arial,helvetica,sans-serif;
-}
-h4 {
- font-family: verdana,arial,helvetica,sans-serif;
-}
-.classMethod {
- font-family: courier,monospace;
- font-weight: bold;
- background: #EEEEE0;
-}
-.instanceMethod {
- font-family: courier,sans-serif;
- background: #EEEEE0;
-}
diff --git a/vendor/madeleine-0.7.1/generate_rdoc.rb b/vendor/madeleine-0.7.1/generate_rdoc.rb
deleted file mode 100755
index b4e0ba7b..00000000
--- a/vendor/madeleine-0.7.1/generate_rdoc.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/local/bin/ruby
-
-`rdoc lib --op docs/api`
diff --git a/vendor/madeleine-0.7.1/install.rb b/vendor/madeleine-0.7.1/install.rb
deleted file mode 100755
index e624774e..00000000
--- a/vendor/madeleine-0.7.1/install.rb
+++ /dev/null
@@ -1,1098 +0,0 @@
-#
-# This file is automatically generated. DO NOT MODIFY!
-#
-# install.rb
-#
-# Copyright (c) 2000-2003 Minero Aoki
-#
-# This program is free software.
-# You can distribute/modify this program under the terms of
-# the GNU Lesser General Public License version 2.
-#
-
-### begin compat.rb
-
-module Enumerable
- methods = instance_methods()
-
- unless methods.include?('map')
- alias map collect
- end
-
- unless methods.include?('select')
- alias select find_all
- end
-
- unless methods.include?('reject')
- def reject
- result = []
- each do |i|
- result.push i unless yield(i)
- end
- result
- end
- end
-
- unless methods.include?('inject')
- def inject( result )
- each do |i|
- result = yield(result, i)
- end
- result
- end
- end
-
- unless methods.include?('any?')
- def any?
- each do |i|
- return true if yield(i)
- end
- false
- end
- end
-end
-
-def File.read_all( fname )
- File.open(fname, 'rb') {|f| return f.read }
-end
-
-def File.write( fname, str )
- File.open(fname, 'wb') {|f| f.write str }
-end
-
-### end compat.rb
-### begin config.rb
-
-if i = ARGV.index(/\A--rbconfig=/)
- file = $'
- ARGV.delete_at(i)
- require file
-else
- require 'rbconfig'
-end
-
-
-class ConfigTable
-
- c = ::Config::CONFIG
-
- rubypath = c['bindir'] + '/' + c['ruby_install_name']
-
- major = c['MAJOR'].to_i
- minor = c['MINOR'].to_i
- teeny = c['TEENY'].to_i
- version = "#{major}.#{minor}"
-
- # ruby ver. >= 1.4.4?
- newpath_p = ((major >= 2) or
- ((major == 1) and
- ((minor >= 5) or
- ((minor == 4) and (teeny >= 4)))))
-
- re = Regexp.new('\A' + Regexp.quote(c['prefix']))
- subprefix = lambda {|path|
- re === path and path.sub(re, '$prefix')
- }
-
- if c['rubylibdir']
- # V < 1.6.3
- stdruby = subprefix.call(c['rubylibdir'])
- siteruby = subprefix.call(c['sitedir'])
- versite = subprefix.call(c['sitelibdir'])
- sodir = subprefix.call(c['sitearchdir'])
- elsif newpath_p
- # 1.4.4 <= V <= 1.6.3
- stdruby = "$prefix/lib/ruby/#{version}"
- siteruby = subprefix.call(c['sitedir'])
- versite = siteruby + '/' + version
- sodir = "$site-ruby/#{c['arch']}"
- else
- # V < 1.4.4
- stdruby = "$prefix/lib/ruby/#{version}"
- siteruby = "$prefix/lib/ruby/#{version}/site_ruby"
- versite = siteruby
- sodir = "$site-ruby/#{c['arch']}"
- end
-
- DESCRIPTER = [
- [ 'prefix', [ c['prefix'],
- 'path',
- 'path prefix of target environment' ] ],
- [ 'std-ruby', [ stdruby,
- 'path',
- 'the directory for standard ruby libraries' ] ],
- [ 'site-ruby-common', [ siteruby,
- 'path',
- 'the directory for version-independent non-standard ruby libraries' ] ],
- [ 'site-ruby', [ versite,
- 'path',
- 'the directory for non-standard ruby libraries' ] ],
- [ 'bin-dir', [ '$prefix/bin',
- 'path',
- 'the directory for commands' ] ],
- [ 'rb-dir', [ '$site-ruby',
- 'path',
- 'the directory for ruby scripts' ] ],
- [ 'so-dir', [ sodir,
- 'path',
- 'the directory for ruby extentions' ] ],
- [ 'data-dir', [ '$prefix/share',
- 'path',
- 'the directory for shared data' ] ],
- [ 'ruby-path', [ rubypath,
- 'path',
- 'path to set to #! line' ] ],
- [ 'ruby-prog', [ rubypath,
- 'name',
- 'the ruby program using for installation' ] ],
- [ 'make-prog', [ 'make',
- 'name',
- 'the make program to compile ruby extentions' ] ],
- [ 'without-ext', [ 'no',
- 'yes/no',
- 'does not compile/install ruby extentions' ] ]
- ]
-
- SAVE_FILE = 'config.save'
-
- def ConfigTable.each_name( &block )
- keys().each(&block)
- end
-
- def ConfigTable.keys
- DESCRIPTER.map {|k,*dummy| k }
- end
-
- def ConfigTable.each_definition( &block )
- DESCRIPTER.each(&block)
- end
-
- def ConfigTable.get_entry( name )
- name, ent = DESCRIPTER.assoc(name)
- ent
- end
-
- def ConfigTable.get_entry!( name )
- get_entry(name) or raise ArgumentError, "no such config: #{name}"
- end
-
- def ConfigTable.add_entry( name, vals )
- ConfigTable::DESCRIPTER.push [name,vals]
- end
-
- def ConfigTable.remove_entry( name )
- get_entry name or raise ArgumentError, "no such config: #{name}"
- DESCRIPTER.delete_if {|n,arr| n == name }
- end
-
- def ConfigTable.config_key?( name )
- get_entry(name) ? true : false
- end
-
- def ConfigTable.bool_config?( name )
- ent = get_entry(name) or return false
- ent[1] == 'yes/no'
- end
-
- def ConfigTable.value_config?( name )
- ent = get_entry(name) or return false
- ent[1] != 'yes/no'
- end
-
- def ConfigTable.path_config?( name )
- ent = get_entry(name) or return false
- ent[1] == 'path'
- end
-
-
- class << self
- alias newobj new
-
- def new
- c = newobj()
- c.__send__ :init
- c
- end
-
- def load
- c = newobj()
- raise InstallError, "#{File.basename $0} config first"\
- unless FileTest.file?(SAVE_FILE)
- File.foreach(SAVE_FILE) do |line|
- k, v = line.split(/=/, 2)
- c.instance_eval {
- @table[k] = v.strip
- }
- end
- c
- end
- end
-
- def initialize
- @table = {}
- end
-
- def init
- DESCRIPTER.each do |k, (default, vname, desc, default2)|
- @table[k] = default
- end
- end
- private :init
-
- def save
- File.open(SAVE_FILE, 'w') {|f|
- @table.each do |k, v|
- f.printf "%s=%s\n", k, v if v
- end
- }
- end
-
- def []=( k, v )
- ConfigTable.config_key? k or raise InstallError, "unknown config option #{k}"
- if ConfigTable.path_config? k
- @table[k] = (v[0,1] != '$') ? File.expand_path(v) : v
- else
- @table[k] = v
- end
- end
-
- def []( key )
- @table[key] or return nil
- @table[key].gsub(%r<\$([^/]+)>) { self[$1] }
- end
-
- def set_raw( key, val )
- @table[key] = val
- end
-
- def get_raw( key )
- @table[key]
- end
-
-end
-
-
-module MetaConfigAPI
-
- def eval_file_ifexist( fname )
- instance_eval File.read_all(fname), fname, 1 if FileTest.file?(fname)
- end
-
- def config_names
- ConfigTable.keys
- end
-
- def config?( name )
- ConfigTable.config_key? name
- end
-
- def bool_config?( name )
- ConfigTable.bool_config? name
- end
-
- def value_config?( name )
- ConfigTable.value_config? name
- end
-
- def path_config?( name )
- ConfigTable.path_config? name
- end
-
- def add_config( name, argname, default, desc )
- ConfigTable.add_entry name,[default,argname,desc]
- end
-
- def add_path_config( name, default, desc )
- add_config name, 'path', default, desc
- end
-
- def add_bool_config( name, default, desc )
- add_config name, 'yes/no', default ? 'yes' : 'no', desc
- end
-
- def set_config_default( name, default )
- if bool_config? name
- ConfigTable.get_entry!(name)[0] = default ? 'yes' : 'no'
- else
- ConfigTable.get_entry!(name)[0] = default
- end
- end
-
- def remove_config( name )
- ent = ConfigTable.get_entry(name)
- ConfigTable.remove_entry name
- ent
- end
-
-end
-
-### end config.rb
-### begin fileop.rb
-
-module FileOperations
-
- def mkdir_p( dname, prefix = nil )
- dname = prefix + dname if prefix
- $stderr.puts "mkdir -p #{dname}" if verbose?
- return if no_harm?
-
- # does not check '/'... it's too abnormal case
- dirs = dname.split(%r<(?=/)>)
- if /\A[a-z]:\z/i === dirs[0]
- disk = dirs.shift
- dirs[0] = disk + dirs[0]
- end
- dirs.each_index do |idx|
- path = dirs[0..idx].join('')
- Dir.mkdir path unless dir? path
- end
- end
-
- def rm_f( fname )
- $stderr.puts "rm -f #{fname}" if verbose?
- return if no_harm?
-
- if File.exist? fname or File.symlink? fname
- File.chmod 0777, fname
- File.unlink fname
- end
- end
-
- def rm_rf( dn )
- $stderr.puts "rm -rf #{dn}" if verbose?
- return if no_harm?
-
- Dir.chdir dn
- Dir.foreach('.') do |fn|
- next if fn == '.'
- next if fn == '..'
- if dir? fn
- verbose_off {
- rm_rf fn
- }
- else
- verbose_off {
- rm_f fn
- }
- end
- end
- Dir.chdir '..'
- Dir.rmdir dn
- end
-
- def mv( src, dest )
- rm_f dest
- begin
- File.link src, dest
- rescue
- File.write dest, File.read_all(src)
- File.chmod File.stat(src).mode, dest
- end
- rm_f src
- end
-
- def install( from, dest, mode, prefix = nil )
- $stderr.puts "install #{from} #{dest}" if verbose?
- return if no_harm?
-
- realdest = prefix + dest if prefix
- if dir? realdest
- realdest += '/' + File.basename(from)
- end
- str = File.read_all(from)
- if diff? str, realdest
- verbose_off {
- rm_f realdest if File.exist? realdest
- }
- File.write realdest, str
- File.chmod mode, realdest
-
- File.open(objdir + '/InstalledFiles', 'a') {|f| f.puts realdest }
- end
- end
-
- def diff?( orig, targ )
- return true unless File.exist? targ
- orig != File.read_all(targ)
- end
-
- def command( str )
- $stderr.puts str if verbose?
- system str or raise RuntimeError, "'system #{str}' failed"
- end
-
- def ruby( str )
- command config('ruby-prog') + ' ' + str
- end
-
- def dir?( dname )
- # for corrupted windows stat()
- File.directory?((dname[-1,1] == '/') ? dname : dname + '/')
- end
-
- def all_files_in( dname )
- Dir.open(dname) {|d|
- return d.select {|n| FileTest.file? "#{dname}/#{n}" }
- }
- end
-
- REJECT_DIRS = %w(
- CVS SCCS RCS CVS.adm
- )
-
- def all_dirs_in( dname )
- Dir.open(dname) {|d|
- return d.select {|n| dir? "#{dname}/#{n}" } - %w(. ..) - REJECT_DIRS
- }
- end
-
-end
-
-### end fileop.rb
-### begin base.rb
-
-class InstallError < StandardError; end
-
-
-class Installer
-
- Version = '3.1.4'
- Copyright = 'Copyright (c) 2000-2003 Minero Aoki'
-
-
- @toplevel = nil
-
- def self.declare_toplevel_installer( inst )
- raise ArgumentError, 'two toplevel installers declared' if @toplevel
- @toplevel = inst
- end
-
- def self.toplevel_installer
- @toplevel
- end
-
-
- FILETYPES = %w( bin lib ext data )
-
- include FileOperations
-
- def initialize( config, opt, srcroot, objroot )
- @config = config
- @options = opt
- @srcdir = File.expand_path(srcroot)
- @objdir = File.expand_path(objroot)
- @currdir = '.'
- end
-
- def inspect
- "#<#{self.class} #{__id__}>"
- end
-
- #
- # configs/options
- #
-
- def get_config( key )
- @config[key]
- end
-
- alias config get_config
-
- def set_config( key, val )
- @config[key] = val
- end
-
- def no_harm?
- @options['no-harm']
- end
-
- def verbose?
- @options['verbose']
- end
-
- def verbose_off
- save, @options['verbose'] = @options['verbose'], false
- yield
- @options['verbose'] = save
- end
-
- #
- # srcdir/objdir
- #
-
- attr_reader :srcdir
- alias srcdir_root srcdir
- alias package_root srcdir
-
- def curr_srcdir
- "#{@srcdir}/#{@currdir}"
- end
-
- attr_reader :objdir
- alias objdir_root objdir
-
- def curr_objdir
- "#{@objdir}/#{@currdir}"
- end
-
- def srcfile( path )
- curr_srcdir + '/' + path
- end
-
- def srcexist?( path )
- File.exist? srcfile(path)
- end
-
- def srcdirectory?( path )
- dir? srcfile(path)
- end
-
- def srcfile?( path )
- FileTest.file? srcfile(path)
- end
-
- def srcentries( path = '.' )
- Dir.open(curr_srcdir + '/' + path) {|d|
- return d.to_a - %w(. ..) - hookfilenames
- }
- end
-
- def srcfiles( path = '.' )
- srcentries(path).select {|fname|
- FileTest.file? File.join(curr_srcdir, path, fname)
- }
- end
-
- def srcdirectories( path = '.' )
- srcentries(path).select {|fname|
- dir? File.join(curr_srcdir, path, fname)
- }
- end
-
- def dive_into( rel )
- return unless dir?("#{@srcdir}/#{rel}")
-
- dir = File.basename(rel)
- Dir.mkdir dir unless dir?(dir)
- prevdir = Dir.pwd
- Dir.chdir dir
- $stderr.puts '---> ' + rel if verbose?
- @currdir = rel
- yield
- Dir.chdir prevdir
- $stderr.puts '<--- ' + rel if verbose?
- @currdir = File.dirname(rel)
- end
-
- #
- # TASK config
- #
-
- def exec_config
- exec_task_traverse 'config'
- end
-
- def config_dir_bin( rel )
- end
-
- def config_dir_lib( rel )
- end
-
- def config_dir_ext( rel )
- extconf if extdir? curr_srcdir
- end
-
- def extconf
- opt = @options['config-opt'].join(' ')
- command "#{config('ruby-prog')} #{curr_srcdir}/extconf.rb #{opt}"
- end
-
- def config_dir_data( rel )
- end
-
- #
- # TASK setup
- #
-
- def exec_setup
- exec_task_traverse 'setup'
- end
-
- def setup_dir_bin( relpath )
- all_files_in(curr_srcdir()).each do |fname|
- add_rubypath "#{curr_srcdir}/#{fname}"
- end
- end
-
- SHEBANG_RE = /\A\#!\s*\S*ruby\S*/
-
- def add_rubypath( path )
- $stderr.puts %Q if verbose?
- return if no_harm?
-
- tmpfile = File.basename(path) + '.tmp'
- begin
- File.open(path) {|r|
- File.open(tmpfile, 'w') {|w|
- first = r.gets
- return unless SHEBANG_RE === first # reject '/usr/bin/env ruby'
-
- w.print first.sub(SHEBANG_RE, '#!' + config('ruby-path'))
- w.write r.read
- } }
- mv tmpfile, File.basename(path)
- ensure
- rm_f tmpfile if File.exist? tmpfile
- end
- end
-
- def setup_dir_lib( relpath )
- end
-
- def setup_dir_ext( relpath )
- make if extdir?(curr_srcdir)
- end
-
- def setup_dir_data( relpath )
- end
-
- #
- # TASK install
- #
-
- def exec_install
- exec_task_traverse 'install'
- end
-
- def install_dir_bin( rel )
- install_files target_filenames(), config('bin-dir') + '/' + rel, 0755
- end
-
- def install_dir_lib( rel )
- install_files target_filenames(), config('rb-dir') + '/' + rel, 0644
- end
-
- def install_dir_ext( rel )
- install_dir_ext_main File.dirname(rel) if extdir?(curr_srcdir)
- end
-
- def install_dir_ext_main( rel )
- install_files allext('.'), config('so-dir') + '/' + rel, 0555
- end
-
- def install_dir_data( rel )
- install_files target_filenames(), config('data-dir') + '/' + rel, 0644
- end
-
- def install_files( list, dest, mode )
- mkdir_p dest, @options['install-prefix']
- list.each do |fname|
- install fname, dest, mode, @options['install-prefix']
- end
- end
-
- def target_filenames
- if FileTest.file? "#{curr_srcdir()}/MANIFEST"
- mapdir(target_filenames_MANIFEST())
- else
- mapdir(target_filenames_AUTO())
- end
- end
-
- def mapdir( filelist )
- filelist.map {|fname|
- if File.exist? fname # current objdir == '.'
- fname
- else
- File.join(curr_srcdir(), fname)
- end
- }
- end
-
- def target_filenames_MANIFEST
- File.read_all("#{curr_srcdir()}/MANIFEST").split
- end
-
- # picked up many entries from cvs-1.11.1/src/ignore.c
- REJECT_PATTERNS = %w(
- core RCSLOG tags TAGS .make.state
- .nse_depinfo #* .#* cvslog.* ,* .del-* *.a *.olb *.o *.obj
- *.so *.Z *~ *.old *.elc *.ln *.bak *.BAK *.orig *.rej *.exe _$* *$
-
- *.org *.in .*
- ).map {|pattern|
- Regexp.compile('\A' + pattern.gsub(/[\.\$]/) {|s| '\\' + s }.gsub(/\*/, '.*') + '\z')
- }
-
- def target_filenames_AUTO
- (existfiles() - hookfiles()).reject {|fname|
- REJECT_PATTERNS.any? {|re| re === fname }
- }
- end
-
- def existfiles
- all_files_in(curr_srcdir()) | all_files_in(curr_objdir())
- end
-
- def hookfiles
- %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
- %w( config setup install clean ).map {|t| sprintf(fmt, t) }
- }.flatten
- end
-
- def allext( dir )
- _allext(dir) or raise InstallError,
- "no extention exists: Have you done 'ruby #{$0} setup' ?"
- end
-
- DLEXT = /\.#{ ::Config::CONFIG['DLEXT'] }\z/
-
- def _allext( dir )
- Dir.open(dir) {|d|
- return d.select {|fname| DLEXT === fname }
- }
- end
-
- #
- # TASK clean
- #
-
- def exec_clean
- exec_task_traverse 'clean'
- rm_f 'config.save'
- rm_f 'InstalledFiles'
- end
-
- def clean_dir_bin( rel )
- end
-
- def clean_dir_lib( rel )
- end
-
- def clean_dir_ext( rel )
- make 'clean' if FileTest.file?('Makefile')
- end
-
- def clean_dir_data( rel )
- end
-
- #
- # TASK distclean
- #
-
- def exec_distclean
- exec_task_traverse 'distclean'
- rm_f 'config.save'
- rm_f 'InstalledFiles'
- end
-
- def distclean_dir_bin( rel )
- end
-
- def distclean_dir_lib( rel )
- end
-
- def distclean_dir_ext( rel )
- make 'distclean' if FileTest.file?('Makefile')
- end
-
- #
- # lib
- #
-
- def make( task = '' )
- command config('make-prog') + ' ' + task
- end
-
- def exec_task_traverse( task )
- run_hook 'pre-' + task
- FILETYPES.each do |type|
- if config('without-ext') == 'yes' and type == 'ext'
- $stderr.puts 'skipping ext/* by user option' if verbose?
- next
- end
- traverse task, type, task + '_dir_' + type
- end
- run_hook 'post-' + task
- end
-
- def traverse( task, rel, mid )
- dive_into(rel) {
- run_hook 'pre-' + task
- __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
- all_dirs_in(curr_srcdir()).each do |d|
- traverse task, rel + '/' + d, mid
- end
- run_hook 'post-' + task
- }
- end
-
- def run_hook( name )
- try_run_hook curr_srcdir + '/' + name or
- try_run_hook curr_srcdir + '/' + name + '.rb'
- end
-
- def try_run_hook( fname )
- return false unless FileTest.file?(fname)
-
- env = self.dup
- begin
- env.instance_eval File.read_all(fname), fname, 1
- rescue
- raise InstallError, "hook #{fname} failed:\n" + $!.message
- end
- true
- end
-
- def extdir?( dir )
- File.exist? dir + '/MANIFEST'
- end
-
-end
-
-### end base.rb
-### begin toplevel.rb
-
-class ToplevelInstaller < Installer
-
- def self.invoke
- new(File.dirname($0)).invoke
- end
-
-
- TASKS = [
- [ 'config', 'saves your configurations' ],
- [ 'show', 'shows current configuration' ],
- [ 'setup', 'compiles extention or else' ],
- [ 'install', 'installs files' ],
- [ 'clean', "does `make clean' for each extention" ],
- [ 'distclean',"does `make distclean' for each extention" ]
- ]
-
-
- def initialize( root )
- super nil, {'verbose' => true}, root, '.'
- Installer.declare_toplevel_installer self
- end
-
-
- def invoke
- run_metaconfigs
-
- case task = parsearg_global()
- when 'config'
- @config = ConfigTable.new
- else
- @config = ConfigTable.load
- end
- parsearg_TASK task
-
- exectask task
- end
-
- include MetaConfigAPI
-
- def run_metaconfigs
- eval_file_ifexist "#{srcdir_root()}/metaconfig"
- end
-
-
- def exectask( task )
- if task == 'show'
- exec_show
- else
- try task
- end
- end
-
- def try( task )
- $stderr.printf "#{File.basename $0}: entering %s phase...\n", task if verbose?
- begin
- __send__ 'exec_' + task
- rescue
- $stderr.printf "%s failed\n", task
- raise
- end
- $stderr.printf "#{File.basename $0}: %s done.\n", task if verbose?
- end
-
- #
- # processing arguments
- #
-
- def parsearg_global
- task_re = /\A(?:#{TASKS.map {|i| i[0] }.join '|'})\z/
-
- while arg = ARGV.shift
- case arg
- when /\A\w+\z/
- task_re === arg or raise InstallError, "wrong task: #{arg}"
- return arg
-
- when '-q', '--quiet'
- @options['verbose'] = false
-
- when '--verbose'
- @options['verbose'] = true
-
- when '-h', '--help'
- print_usage $stdout
- exit 0
-
- when '-v', '--version'
- puts "#{File.basename $0} version #{Version}"
- exit 0
-
- when '--copyright'
- puts Copyright
- exit 0
-
- else
- raise InstallError, "unknown global option '#{arg}'"
- end
- end
-
- raise InstallError, "No task or global option given.
-Typical installation procedure is:
- $ ruby #{File.basename $0} config
- $ ruby #{File.basename $0} setup
- # ruby #{File.basename $0} install (may require root privilege)
-"
- end
-
-
- def parsearg_TASK( task )
- mid = "parsearg_#{task}"
- if respond_to? mid, true
- __send__ mid
- else
- ARGV.empty? or
- raise InstallError, "#{task}: unknown options: #{ARGV.join ' '}"
- end
- end
-
- def parsearg_config
- re = /\A--(#{ConfigTable.keys.join '|'})(?:=(.*))?\z/
- @options['config-opt'] = []
-
- while i = ARGV.shift
- if /\A--?\z/ === i
- @options['config-opt'] = ARGV.dup
- break
- end
- m = re.match(i) or raise InstallError, "config: unknown option #{i}"
- name, value = m.to_a[1,2]
- if value
- if ConfigTable.bool_config?(name)
- /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i === value or raise InstallError, "config: --#{name} allows only yes/no for argument"
- value = (/\Ay(es)?|\At(rue)/i === value) ? 'yes' : 'no'
- end
- else
- ConfigTable.bool_config?(name) or raise InstallError, "config: --#{name} requires argument"
- value = 'yes'
- end
- @config[name] = value
- end
- end
-
- def parsearg_install
- @options['no-harm'] = false
- @options['install-prefix'] = ''
- while a = ARGV.shift
- case a
- when /\A--no-harm\z/
- @options['no-harm'] = true
- when /\A--prefix=(.*)\z/
- path = $1
- path = File.expand_path(path) unless path[0,1] == '/'
- @options['install-prefix'] = path
- else
- raise InstallError, "install: unknown option #{a}"
- end
- end
- end
-
-
- def print_usage( out )
- out.puts 'Typical Installation Procedure:'
- out.puts " $ ruby #{File.basename $0} config"
- out.puts " $ ruby #{File.basename $0} setup"
- out.puts " # ruby #{File.basename $0} install (may require root privilege)"
- out.puts
- out.puts 'Detailed Usage:'
- out.puts " ruby #{File.basename $0} "
- out.puts " ruby #{File.basename $0} [] []"
-
- fmt = " %-20s %s\n"
- out.puts
- out.puts 'Global options:'
- out.printf fmt, '-q,--quiet', 'suppress message outputs'
- out.printf fmt, ' --verbose', 'output messages verbosely'
- out.printf fmt, '-h,--help', 'print this message'
- out.printf fmt, '-v,--version', 'print version and quit'
- out.printf fmt, ' --copyright', 'print copyright and quit'
-
- out.puts
- out.puts 'Tasks:'
- TASKS.each do |name, desc|
- out.printf " %-10s %s\n", name, desc
- end
-
- out.puts
- out.puts 'Options for config:'
- ConfigTable.each_definition do |name, (default, arg, desc, default2)|
- out.printf " %-20s %s [%s]\n",
- '--'+ name + (ConfigTable.bool_config?(name) ? '' : '='+arg),
- desc,
- default2 || default
- end
- out.printf " %-20s %s [%s]\n",
- '--rbconfig=path', 'your rbconfig.rb to load', "running ruby's"
-
- out.puts
- out.puts 'Options for install:'
- out.printf " %-20s %s [%s]\n",
- '--no-harm', 'only display what to do if given', 'off'
- out.printf " %-20s %s [%s]\n",
- '--prefix', 'install path prefix', '$prefix'
-
- out.puts
- end
-
- #
- # config
- #
-
- def exec_config
- super
- @config.save
- end
-
- #
- # show
- #
-
- def exec_show
- ConfigTable.each_name do |k|
- v = @config.get_raw(k)
- if not v or v.empty?
- v = '(not specified)'
- end
- printf "%-10s %s\n", k, v
- end
- end
-
-end
-
-### end toplevel.rb
-
-if $0 == __FILE__
- begin
- ToplevelInstaller.invoke
- rescue
- raise if $DEBUG
- $stderr.puts $!.message
- $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
- exit 1
- end
-end
diff --git a/vendor/madeleine-0.7.1/lib/madeleine.rb b/vendor/madeleine-0.7.1/lib/madeleine.rb
deleted file mode 100755
index 3b6f8fdb..00000000
--- a/vendor/madeleine-0.7.1/lib/madeleine.rb
+++ /dev/null
@@ -1,420 +0,0 @@
-#
-# Madeleine - Ruby Object Prevalence
-#
-# Author:: Anders Bengtsson
-# Copyright:: Copyright (c) 2003-2004
-#
-# Usage:
-#
-# require 'madeleine'
-#
-# madeleine = SnapshotMadeleine.new("my_example_storage") {
-# SomeExampleApplication.new()
-# }
-#
-# madeleine.execute_command(command)
-#
-
-module Madeleine
-
- require 'thread'
- require 'sync'
- require 'madeleine/files'
-
- MADELEINE_VERSION = "0.7.1"
-
- class SnapshotMadeleine
-
- # Builds a new Madeleine instance. If there is a snapshot available
- # then the system will be created from that, otherwise
- # new_system will be used. The state of the system will
- # then be restored from the command logs.
- #
- # You can provide your own snapshot marshaller, for instance using
- # YAML or SOAP, instead of Ruby's built-in marshaller. The
- # snapshot_marshaller must respond to
- # load(stream) and dump(object, stream). You
- # must use the same marshaller every time for a system.
- #
- # See: DefaultSnapshotMadeleine
- #
- # * directory_name - Storage directory to use. Will be created if needed.
- # * snapshot_marshaller - Marshaller to use for system snapshots. (Optional)
- # * new_system_block - Block to create a new system (if no stored system was found).
- def self.new(directory_name, snapshot_marshaller=Marshal, &new_system_block)
- log_factory = DefaultLogFactory.new
- logger = Logger.new(directory_name,
- log_factory)
- snapshotter = Snapshotter.new(directory_name,
- snapshot_marshaller)
- lock = DefaultLock.new
- recoverer = Recoverer.new(directory_name,
- snapshot_marshaller)
- system = recoverer.recover_snapshot(new_system_block)
-
- executer = Executer.new(system)
- recoverer.recover_logs(executer)
- DefaultSnapshotMadeleine.new(system, logger, snapshotter, lock, executer)
- end
- end
-
- class DefaultSnapshotMadeleine
-
- # The prevalent system
- attr_reader :system
-
- def initialize(system, logger, snapshotter, lock, executer)
- @system = system
- @logger = logger
- @snapshotter = snapshotter
- @lock = lock
- @executer = executer
-
- @closed = false
- end
-
- # Execute a command on the prevalent system.
- #
- # Commands must have a method execute(aSystem).
- # Otherwise an error, Madeleine::InvalidCommandException,
- # will be raised.
- #
- # The return value from the command's execute() method is returned.
- #
- # * command - The command to execute on the system.
- def execute_command(command)
- verify_command_sane(command)
- @lock.synchronize {
- raise "closed" if @closed
- @logger.store(command)
- @executer.execute(command)
- }
- end
-
- # Execute a query on the prevalent system.
- #
- # Only differs from execute_command in that the command/query isn't logged, and
- # therefore isn't allowed to modify the system. A shared lock is held, preventing others
- # from modifying the system while the query is running.
- #
- # * query - The query command to execute
- def execute_query(query)
- @lock.synchronize_shared {
- @executer.execute(query)
- }
- end
-
- # Take a snapshot of the current system.
- #
- # You need to regularly take a snapshot of a running system,
- # otherwise the logs will grow big and restarting the system will take a
- # long time. Your backups must also be done from the snapshot files,
- # since you can't make a consistent backup of a live log.
- #
- # A practical way of doing snapshots is a timer thread:
- #
- # Thread.new(madeleine) {|madeleine|
- # while true
- # sleep(60 * 60 * 24) # 24 hours
- # madeleine.take_snapshot
- # end
- # }
- def take_snapshot
- @lock.synchronize {
- @logger.close
- @snapshotter.take(@system)
- @logger.reset
- }
- end
-
- # Close the system.
- #
- # The log file is closed and no new commands can be received
- # by this Madeleine.
- def close
- @lock.synchronize {
- @logger.close
- @closed = true
- }
- end
-
- private
-
- def verify_command_sane(command)
- unless command.respond_to?(:execute)
- raise InvalidCommandException.new("Commands must have an 'execute' method")
- end
- end
- end
-
- class InvalidCommandException < Exception
- end
-
- #
- # Internal classes below
- #
-
- FILE_COUNTER_SIZE = 21 #:nodoc:
-
- class DefaultLock #:nodoc:
-
- def initialize
- @lock = Sync.new
- end
-
- def synchronize(&block)
- @lock.synchronize(&block)
- end
-
- def synchronize_shared(&block)
- @lock.synchronize(:SH, &block)
- end
- end
-
- class Executer #:nodoc:
-
- def initialize(system)
- @system = system
- @in_recovery = false
- end
-
- def execute(command)
- begin
- command.execute(@system)
- rescue
- raise unless @in_recovery
- end
- end
-
- def recovery
- begin
- @in_recovery = true
- yield
- ensure
- @in_recovery = false
- end
- end
- end
-
- class Recoverer #:nodoc:
-
- def initialize(directory_name, marshaller)
- @directory_name, @marshaller = directory_name, marshaller
- end
-
- def recover_snapshot(new_system_block)
- system = nil
- id = SnapshotFile.highest_id(@directory_name)
- if id > 0
- snapshot_file = SnapshotFile.new(@directory_name, id).name
- open(snapshot_file, "rb") {|snapshot|
- system = @marshaller.load(snapshot)
- }
- else
- system = new_system_block.call
- end
- system
- end
-
- def recover_logs(executer)
- executer.recovery {
- CommandLog.log_file_names(@directory_name, FileService.new).each {|file_name|
- open(@directory_name + File::SEPARATOR + file_name, "rb") {|log|
- recover_log(executer, log)
- }
- }
- }
- end
-
- private
-
- def recover_log(executer, log)
- while ! log.eof?
- command = Marshal.load(log)
- executer.execute(command)
- end
- end
- end
-
- class NumberedFile #:nodoc:
-
- def initialize(path, name, id)
- @path, @name, @id = path, name, id
- end
-
- def name
- result = @path
- result += File::SEPARATOR
- result += sprintf("%0#{FILE_COUNTER_SIZE}d", @id)
- result += '.'
- result += @name
- end
- end
-
- class CommandLog #:nodoc:
-
- def self.log_file_names(directory_name, file_service)
- return [] unless file_service.exist?(directory_name)
- result = file_service.dir_entries(directory_name).select {|name|
- name =~ /^\d{#{FILE_COUNTER_SIZE}}\.command_log$/
- }
- result.each {|name| name.untaint }
- result.sort!
- result
- end
-
- def initialize(path, file_service)
- id = self.class.highest_log(path, file_service) + 1
- numbered_file = NumberedFile.new(path, "command_log", id)
- @file = file_service.open(numbered_file.name, 'wb')
- end
-
- def close
- @file.close
- end
-
- def store(command)
- Marshal.dump(command, @file)
- @file.flush
- @file.fsync
- end
-
- def self.highest_log(directory_name, file_service)
- highest = 0
- log_file_names(directory_name, file_service).each {|file_name|
- match = /^(\d{#{FILE_COUNTER_SIZE}})/.match(file_name)
- n = match[1].to_i
- if n > highest
- highest = n
- end
- }
- highest
- end
- end
-
- class DefaultLogFactory #:nodoc:
- def create_log(directory_name)
- CommandLog.new(directory_name, FileService.new)
- end
- end
-
- class Logger #:nodoc:
-
- def initialize(directory_name, log_factory)
- @directory_name = directory_name
- @log_factory = log_factory
- @log = nil
- @pending_tick = nil
- ensure_directory_exists
- end
-
- def ensure_directory_exists
- if ! File.exist?(@directory_name)
- Dir.mkdir(@directory_name)
- end
- end
-
- def reset
- close
- delete_log_files
- end
-
- def store(command)
- if command.kind_of?(Madeleine::Clock::Tick)
- @pending_tick = command
- else
- if @pending_tick
- internal_store(@pending_tick)
- @pending_tick = nil
- end
- internal_store(command)
- end
- end
-
- def internal_store(command)
- if @log.nil?
- open_new_log
- end
- @log.store(command)
- end
-
- def close
- return if @log.nil?
- @log.close
- @log = nil
- end
-
- private
-
- def delete_log_files
- Dir.glob(@directory_name + File::SEPARATOR + "*.command_log").each {|name|
- name.untaint
- File.delete(name)
- }
- end
-
- def open_new_log
- @log = @log_factory.create_log(@directory_name)
- end
- end
-
- class SnapshotFile < NumberedFile #:nodoc:
-
- def self.highest_id(directory_name)
- return 0 unless File.exist?(directory_name)
- suffix = "snapshot"
- highest = 0
- Dir.foreach(directory_name) {|file_name|
- match = /^(\d{#{FILE_COUNTER_SIZE}}\.#{suffix}$)/.match(file_name)
- next unless match
- n = match[1].to_i
- if n > highest
- highest = n
- end
- }
- highest
- end
-
- def self.next(directory_name)
- new(directory_name, highest_id(directory_name) + 1)
- end
-
- def initialize(directory_name, id)
- super(directory_name, "snapshot", id)
- end
- end
-
- class Snapshotter #:nodoc:
-
- def initialize(directory_name, marshaller)
- @directory_name, @marshaller = directory_name, marshaller
- end
-
- def take(system)
- numbered_file = SnapshotFile.next(@directory_name)
- name = numbered_file.name
- open(name + '.tmp', 'wb') {|snapshot|
- @marshaller.dump(system, snapshot)
- snapshot.flush
- snapshot.fsync
- }
- File.rename(name + '.tmp', name)
- end
- end
-
- module Clock #:nodoc:
- class Tick #:nodoc:
-
- def initialize(time)
- @time = time
- end
-
- def execute(system)
- system.clock.forward_to(@time)
- end
- end
- end
-end
-
-SnapshotMadeleine = Madeleine::SnapshotMadeleine
-
diff --git a/vendor/madeleine-0.7.1/lib/madeleine/automatic.rb b/vendor/madeleine-0.7.1/lib/madeleine/automatic.rb
deleted file mode 100755
index 447d5ec3..00000000
--- a/vendor/madeleine-0.7.1/lib/madeleine/automatic.rb
+++ /dev/null
@@ -1,418 +0,0 @@
-require 'yaml'
-require 'madeleine/zmarshal'
-require 'soap/marshal'
-
-module Madeleine
-
-# Automatic commands for Madeleine
-#
-# Author:: Stephen Sykes
-# Copyright:: Copyright (C) 2003-2004
-# Version:: 0.41
-#
-# This module provides a way of automatically generating command objects for madeleine to
-# store. It works by making a proxy object for all objects of any classes in which it is included.
-# Method calls to these objects are intercepted, and stored as a command before being
-# passed on to the real receiver. The command objects remember which object the command was
-# destined for by using a pair of internal ids that are contained in each of the proxy objects.
-#
-# There is also a mechanism for specifying which methods not to intercept calls to by using
-# automatic_read_only, and its opposite automatic_read_write.
-#
-# Should you require it, the snapshots can be stored as yaml, and can be compressed. Just pass
-# the marshaller you want to use as the second argument to AutomaticSnapshotMadeleine.new.
-# If the passed marshaller did not successfully deserialize the latest snapshot, the system
-# will try to automatically detect and read either Marshal, YAML, SOAP, or their corresponding
-# compressed versions.
-#
-# This module is designed to work correctly in the case there are multiple madeleine systems in use by
-# a single program, and is also safe to use with threads.
-#
-# Usage:
-#
-# require 'madeleine'
-# require 'madeleine/automatic'
-#
-# class A
-# include Madeleine::Automatic::Interceptor
-# attr_reader :foo
-# automatic_read_only :foo
-# def initialize(param1, ...)
-# ...
-# end
-# def some_method(paramA, ...)
-# ...
-# end
-# automatic_read_only
-# def bigfoo
-# foo.upcase
-# end
-# end
-#
-# mad = AutomaticSnapshotMadeleine.new("storage_directory") { A.new(param1, ...) }
-#
-# mad.system.some_method(paramA, ...) # logged as a command by madeleine
-# print mad.foo # not logged
-# print mad.bigfoo # not logged
-# mad.take_snapshot
-#
-
- module Automatic
-#
-# This module should be included (at the top) in any classes that are to be persisted.
-# It will intercept method calls and make sure they are converted into commands that are logged by Madeleine.
-# It does this by returning a Prox object that is a proxy for the real object.
-#
-# It also handles automatic_read_only and automatic_read_write, allowing user specification of which methods
-# should be made into commands
-#
- module Interceptor
-#
-# When included, redefine new so that we can return a Prox object instead, and define methods to handle
-# keeping track of which methods are read only
-#
- def self.included(klass)
- class < "")
- x
- end
-
- end
-
-#
-# The AutomaticSnapshotMadeleine class contains an instance of the persister
-# (default is SnapshotMadeleine) and provides additional automatic functionality.
-#
-# The class is instantiated the same way as SnapshotMadeleine:
-# madeleine_sys = AutomaticSnapshotMadeleine.new("storage_directory") { A.new(param1, ...) }
-# The second initialisation parameter is the persister. Supported persisters are:
-#
-# * Marshal (default)
-# * YAML
-# * SOAP::Marshal
-# * Madeleine::ZMarshal.new(Marshal)
-# * Madeleine::ZMarshal.new(YAML)
-# * Madeleine::ZMarshal.new(SOAP::Marshal)
-#
-# The class keeps a record of all the systems that currently exist.
-# Each instance of the class keeps a record of Prox objects in that system by internal id (myid).
-#
-# We also add functionality to take_snapshot in order to set things up so that the custom Prox object
-# marshalling will work correctly.
-#
- class AutomaticSnapshotMadeleine
- attr_accessor :marshaller
- attr_reader :list, :sysid
-
- def initialize(directory_name, marshaller=Marshal, persister=SnapshotMadeleine, &new_system_block)
- @sysid ||= Time.now.to_f.to_s + Thread.current.object_id.to_s # Gererate a new sysid
- @myid_count = 0
- @list = {}
- Thread.current[:system] = self # during system startup system should not create commands
- Thread.critical = true
- @@systems ||= {} # holds systems by sysid
- @@systems[@sysid] = self
- Thread.critical = false
- @marshaller = marshaller # until attrb
- begin
- @persister = persister.new(directory_name, Automatic_marshaller, &new_system_block)
- @list.delete_if {|k,v| # set all the prox objects that now exist to have the right sysid
- begin
- ObjectSpace._id2ref(v).sysid = @sysid
- false
- rescue RangeError
- true # Id was to a GC'd object, delete it
- end
- }
- ensure
- Thread.current[:system] = false
- end
- end
-#
-# Add a proxy object to the list, return the myid for that object
-#
- def add(proxo)
- @list[@myid_count += 1] = proxo.object_id
- @myid_count
- end
-#
-# Restore a marshalled proxy object to list - myid_count is increased as required.
-# If the object already exists in the system then the existing object must be used.
-#
- def restore(proxo)
- if (@list[proxo.myid])
- proxo = myid2ref(proxo.myid)
- else
- @list[proxo.myid] = proxo.object_id
- @myid_count = proxo.myid if (@myid_count < proxo.myid)
- end
- proxo
- end
-#
-# Returns a reference to the object indicated by the internal id supplied.
-#
- def myid2ref(myid)
- raise "Internal id #{myid} not found" unless objid = @list[myid]
- ObjectSpace._id2ref(objid)
- end
-#
-# Take a snapshot of the system.
-#
- def take_snapshot
- begin
- Thread.current[:system] = self
- Thread.current[:snapshot_memory] = {}
- @persister.take_snapshot
- ensure
- Thread.current[:snapshot_memory] = nil
- Thread.current[:system] = false
- end
- end
-#
-# Returns the hash containing the systems.
-#
- def AutomaticSnapshotMadeleine.systems
- @@systems
- end
-#
-# Close method changes the sysid for Prox objects so they can't be mistaken for real ones in a new
-# system before GC gets them
-#
- def close
- begin
- @list.each_key {|k| myid2ref(k).sysid = nil}
- rescue RangeError
- # do nothing
- end
- @persister.close
- end
-
-#
-# Pass on any other calls to the persister
-#
- def method_missing(symbol, *args, &block)
- @persister.send(symbol, *args, &block)
- end
- end
-
-
- module Deserialize #:nodoc:
-#
-# Detect format of an io stream. Leave it rewound.
-#
- def Deserialize.detect(io)
- c = io.getc
- c1 = io.getc
- io.rewind
- if (c == Marshal::MAJOR_VERSION && c1 <= Marshal::MINOR_VERSION)
- Marshal
- elsif (c == 31 && c1 == 139) # gzip magic numbers
- ZMarshal
- else
- while (s = io.gets)
- break if (s !~ /^\s*$/) # ignore blank lines
- end
- io.rewind
- if (s && s =~ /^\s*<\?[xX][mM][lL]/) # " e
- io.rewind
- detected_marshaller = detect(io)
- if (detected_marshaller == ZMarshal)
- zio = Zlib::GzipReader.new(io)
- detected_zmarshaller = detect(zio)
- zio.finish
- io.rewind
- if (detected_zmarshaller)
- ZMarshal.new(detected_zmarshaller).load(io)
- else
- raise e
- end
- elsif (detected_marshaller)
- detected_marshaller.load(io)
- else
- raise e
- end
- end
- end
- end
-
- end
-end
-
-AutomaticSnapshotMadeleine = Madeleine::Automatic::AutomaticSnapshotMadeleine
diff --git a/vendor/madeleine-0.7.1/lib/madeleine/clock.rb b/vendor/madeleine-0.7.1/lib/madeleine/clock.rb
deleted file mode 100755
index 012c6f27..00000000
--- a/vendor/madeleine-0.7.1/lib/madeleine/clock.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-#
-# Copyright(c) Anders Bengtsson 2003
-#
-
-require 'madeleine'
-
-module Madeleine
- module Clock
-
- # Deprecated. Use SnapshotMadeleine instead.
- class ClockedSnapshotMadeleine < ::Madeleine::SnapshotMadeleine # :nodoc:
- end
-
- # Let your system extend this module if you need to access the
- # machine time. Used together with a TimeActor that keeps
- # the clock current.
- module ClockedSystem
-
- # Returns this system's Clock.
- def clock
- unless defined? @clock
- @clock = Clock.new
- end
- @clock
- end
- end
-
- # Sends clock ticks to update a ClockedSystem, so that time can be
- # dealt with in a deterministic way.
- class TimeActor
-
- # Create and launch a new TimeActor
- #
- # * madeleine - The SnapshotMadeleine instance to work on.
- # * delay - Delay between ticks in seconds (Optional).
- def self.launch(madeleine, delay=0.1)
- result = new(madeleine, delay)
- result
- end
-
- # Stops the TimeActor.
- def destroy
- @is_destroyed = true
- @thread.wakeup
- @thread.join
- end
-
- private_class_method :new
-
- private
-
- def initialize(madeleine, delay) #:nodoc:
- @madeleine = madeleine
- @is_destroyed = false
- send_tick
- @thread = Thread.new {
- until @is_destroyed
- sleep(delay)
- send_tick
- end
- }
- end
-
- def send_tick
- @madeleine.execute_command(Tick.new(Time.now))
- end
- end
-
- # Keeps track of time in a ClockedSystem.
- class Clock
- # Returns the system's time as a Ruby Time.
- attr_reader :time
-
- def initialize
- @time = Time.at(0)
- end
-
- def forward_to(newTime)
- @time = newTime
- end
- end
-
- #
- # Internal classes below
- #
-
- # Deprecated. Merged into default implementation.
- class TimeOptimizingLogger < ::Madeleine::Logger # :nodoc:
- end
-
- end
-end
-
-ClockedSnapshotMadeleine = Madeleine::Clock::ClockedSnapshotMadeleine
diff --git a/vendor/madeleine-0.7.1/lib/madeleine/files.rb b/vendor/madeleine-0.7.1/lib/madeleine/files.rb
deleted file mode 100755
index 4276d8d5..00000000
--- a/vendor/madeleine-0.7.1/lib/madeleine/files.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Wrapper for Ruby's file services, replaced during testing
-# so we can run tests without touching a real filesystem.
-#
-
-class FileService
-
- def open(*args)
- super(*args)
- end
-
- def exist?(name)
- File.exist?(name)
- end
-
- def dir_entries(name)
- Dir.entries(name)
- end
-end
diff --git a/vendor/madeleine-0.7.1/lib/madeleine/zmarshal.rb b/vendor/madeleine-0.7.1/lib/madeleine/zmarshal.rb
deleted file mode 100755
index b01210ec..00000000
--- a/vendor/madeleine-0.7.1/lib/madeleine/zmarshal.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-#
-# Author:: Anders Bengtsson
-# Copyright:: Copyright (c) 2004
-#
-
-require 'zlib'
-
-module Madeleine
- #
- # Snapshot marshaller for compressed snapshots.
- #
- # Compresses the snapshots created by another marshaller. Uses either
- # Marshal (the default) or another supplied marshaller.
- #
- # Uses zlib to do on-the-fly compression/decompression.
- #
- # ZMarshal works with Ruby's own Marshal and YAML, but not with SOAP
- # marshalling.
- #
- # Usage:
- #
- # require 'madeleine'
- # require 'madeleine/zmarshal'
- #
- # marshaller = Madeleine::ZMarshal.new(YAML)
- # madeleine = SnapshotMadeleine.new("my_example_storage", marshaller) {
- # SomeExampleApplication.new()
- # }
- #
- class ZMarshal
-
- def initialize(marshaller=Marshal)
- @marshaller = marshaller
- end
-
- def load(stream)
- zstream = Zlib::GzipReader.new(stream)
- begin
- # Buffer into a string first, since GzipReader can't handle
- # Marshal's 0-sized reads and SOAP can't handle streams at all.
- # In a bright future we can revert to reading directly from the
- # stream again.
- buffer = zstream.read
- return @marshaller.load(buffer)
- ensure
- zstream.finish
- end
- end
-
- def dump(system, stream)
- zstream = Zlib::GzipWriter.new(stream)
- begin
- @marshaller.dump(system, zstream)
- ensure
- zstream.finish
- end
- nil
- end
- end
-end
diff --git a/vendor/madeleine-0.7.1/madeleine.gemspec b/vendor/madeleine-0.7.1/madeleine.gemspec
deleted file mode 100755
index cd5d38f8..00000000
--- a/vendor/madeleine-0.7.1/madeleine.gemspec
+++ /dev/null
@@ -1,23 +0,0 @@
-
-require 'rubygems'
-
-spec = Gem::Specification.new do |s|
- s.name = 'madeleine'
- s.version = '0.7.1'
- s.platform = Gem::Platform::RUBY
- s.required_ruby_version = ">= 1.8.1"
- s.summary = "Madeleine is a Ruby implementation of Object Prevalence"
- s.require_path = 'lib'
- s.autorequire = 'madeleine'
- s.author = "Anders Bengtsson"
- s.email = "ndrsbngtssn@yahoo.se"
- s.homepage = "http://madeleine.sourceforge.net"
- s.files = Dir.glob("lib/**/*.rb")
- s.files += Dir.glob("samples/**/*.rb")
- s.files += Dir.glob("contrib/**/*.rb")
- s.files += ['README', 'NEWS', 'COPYING']
-end
-
-if $0 == __FILE__
- Gem::Builder.new(spec).build
-end
diff --git a/vendor/madeleine-0.7.1/samples/.cvsignore b/vendor/madeleine-0.7.1/samples/.cvsignore
deleted file mode 100755
index 5ca652ac..00000000
--- a/vendor/madeleine-0.7.1/samples/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-dictionary-base
-painter-demo
-clock-demo
diff --git a/vendor/madeleine-0.7.1/samples/clock_click.rb b/vendor/madeleine-0.7.1/samples/clock_click.rb
deleted file mode 100755
index c11d16a3..00000000
--- a/vendor/madeleine-0.7.1/samples/clock_click.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-#
-# Simple example of using time with Madeleine.
-#
-
-$LOAD_PATH.unshift(".." + File::SEPARATOR + "lib")
-
-require 'madeleine/clock'
-require 'tk'
-
-# The Clicker keeps track of when it was last clicked.
-#
-# To access the time it extends ClockedSystem, which provides
-# it with the 'clock' attribute.
-#
-class Clicker
- include Madeleine::Clock::ClockedSystem
-
- def initialize
- @last_clicked = nil
- end
-
- def click
- @last_clicked = clock.time
- end
-
- def last_clicked
- return '-' if @last_clicked.nil?
- @last_clicked.to_s
- end
-end
-
-# A command to update the Clicker with.
-#
-class Click
- def execute(system)
- system.click
- end
-end
-
-# Launch a ClockedSnapshotMadeleine.
-#
-# ClockedSnapshotMadeleine works like the regular SnapshotMadeleine, but
-# optimizes away redundant commands from TimeActor.
-#
-madeleine = ClockedSnapshotMadeleine.new("clock-demo") { Clicker.new }
-
-# Launch the TimeActor.
-#
-# This provides time commands, without which the system's time would stand still.
-#
-Madeleine::Clock::TimeActor.launch(madeleine)
-
-clicker = madeleine.system
-
-# The GUI
-
-root = TkRoot.new() { title "Madeleine Clock Example" }
-label = TkLabel.new(root) {
- text "Last clicked " + clicker.last_clicked
- width 40
- pack
-}
-button = TkButton.new(root) {
- text 'Click'
- command proc {
- madeleine.execute_command(Click.new)
- label.text("Last clicked " + clicker.last_clicked)
- }
- pack
-}
-
-Tk.mainloop
-
diff --git a/vendor/madeleine-0.7.1/samples/dictionary_client.rb b/vendor/madeleine-0.7.1/samples/dictionary_client.rb
deleted file mode 100755
index 596eab5f..00000000
--- a/vendor/madeleine-0.7.1/samples/dictionary_client.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Dictionary client
-#
-# See dictionary_server.rb for details
-#
-
-require 'drb'
-
-DRb.start_service
-dictionary = DRbObject.new(nil, "druby://localhost:1234")
-
-if ARGV.length == 1
- puts dictionary.lookup(ARGV[0])
-elsif ARGV.length == 2
- dictionary.add(ARGV[0], ARGV[1])
- puts "Stored"
-else
- puts "Usage: dictionary_client []"
-end
-
-
-
-
diff --git a/vendor/madeleine-0.7.1/samples/dictionary_server.rb b/vendor/madeleine-0.7.1/samples/dictionary_server.rb
deleted file mode 100755
index 76c8e925..00000000
--- a/vendor/madeleine-0.7.1/samples/dictionary_server.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-#
-# A dictionary server using Distributed Ruby (DRb).
-#
-# All modifications to the dictionary are done as commands,
-# while read-only queries (i.e 'lookup') are done directly.
-#
-# First launch this server in the background, then use
-# dictionary_client.rb to look up and add items to the
-# dictionary.
-# You can kill the server at any time. The contents of the
-# dictionary will still be there when you restart it.
-#
-# DRb is available at http://raa.ruby-lang.org/list.rhtml?name=druby
-#
-
-$LOAD_PATH.unshift(".." + File::SEPARATOR + "lib")
-require 'madeleine'
-
-require 'drb'
-
-
-class Dictionary
- def initialize
- @data = {}
- end
-
- def add(key, value)
- @data[key] = value
- end
-
- def lookup(key)
- @data[key]
- end
-end
-
-
-class Addition
- def initialize(key, value)
- @key, @value = key, value
- end
-
- def execute(system)
- system.add(@key, @value)
- end
-end
-
-
-class Lookup
- def initialize(key)
- @key = key
- end
-
- def execute(system)
- system.lookup(@key)
- end
-end
-
-
-class DictionaryServer
-
- def initialize(madeleine)
- @madeleine = madeleine
- @dictionary = madeleine.system
- end
-
- def add(key, value)
- # When adding a new key-value pair we modify the system, so
- # this operation has to be done through a command.
- @madeleine.execute_command(Addition.new(key, value))
- end
-
- def lookup(key)
- # A lookup is a read-only operation, so we can do it as a non-logged
- # query. If we weren't worried about concurrency problems we could
- # have just called @dictionary.lookup(key) directly instead.
- @madeleine.execute_query(Lookup.new(key))
- end
-end
-
-
-madeleine = SnapshotMadeleine.new("dictionary-base") { Dictionary.new }
-
-Thread.new(madeleine) {
- puts "Taking snapshot every 30 seconds."
- while true
- sleep(30)
- madeleine.take_snapshot
- end
-}
-
-DRb.start_service("druby://localhost:1234",
- DictionaryServer.new(madeleine))
-DRb.thread.join
-
diff --git a/vendor/madeleine-0.7.1/samples/painter.rb b/vendor/madeleine-0.7.1/samples/painter.rb
deleted file mode 100755
index b9d21658..00000000
--- a/vendor/madeleine-0.7.1/samples/painter.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-#
-# Simple drawing program to show Madeleine's logging feature.
-#
-# When you restart the program, your old artwork is still there.
-#
-# (Note: The GUI components used here aren't marshal-able,
-# so in a real app you would have to do custom marshaling for
-# the Painter class to get working snapshots. Then again, in a real
-# app you wouldn't use the GUI components to hold the app's data,
-# would you?)
-#
-
-$LOAD_PATH.unshift(".." + File::SEPARATOR + "lib")
-
-require 'madeleine'
-
-require 'tkclass'
-
-class Painter
-
- def initialize(canvas)
- @canvas = canvas
- end
-
- def draw(x, y)
- line = Line.new(@canvas, x, y, x + 1, y + 1)
- line.fill('black')
- end
-end
-
-class PaintCommand
-
- def initialize(x, y)
- @x, @y = x, y
- end
-
- def execute(system)
- system.draw(@x, @y)
- end
-end
-
-root = TkRoot.new() { title "Madeleine Painter" }
-canvas = Canvas.new(root)
-canvas.pack
-
-$madeleine = Madeleine::SnapshotMadeleine.new("painter-demo") { Painter.new(canvas) }
-
-canvas.bind("1",
- proc {|x, y|
- $madeleine.execute_command(PaintCommand.new(x, y))
- },
- "%x %y")
-canvas.bind("B1-Motion",
- proc {|x, y|
- $madeleine.execute_command(PaintCommand.new(x, y))
- },
- "%x %y")
-
-Tk.mainloop
-
diff --git a/vendor/madeleine-0.7.1/test/test.rb b/vendor/madeleine-0.7.1/test/test.rb
deleted file mode 100755
index e252a53f..00000000
--- a/vendor/madeleine-0.7.1/test/test.rb
+++ /dev/null
@@ -1,320 +0,0 @@
-#!/usr/bin/env ruby
-#
-
-$LOAD_PATH.unshift("lib")
-$LOAD_PATH.unshift("test")
-
-require 'madeleine'
-require 'test/unit'
-
-
-class Append
- def initialize(value)
- @value = value
- end
-
- def execute(system)
- system << @value
- end
-end
-
-
-module TestUtils
- def delete_directory(directory_name)
- return unless File.exists?(directory_name)
- Dir.foreach(directory_name) do |file|
- next if file == "."
- next if file == ".."
- assert(File.delete(directory_name + File::SEPARATOR + file) == 1,
- "Unable to delete #{file}")
- end
- Dir.delete(directory_name)
- end
-end
-
-
-class SnapshotMadeleineTest < Test::Unit::TestCase
- include TestUtils
-
- def teardown
- delete_directory(persistence_base)
- end
-
- def persistence_base
- "closing-test"
- end
-
- def test_closing
- madeleine = SnapshotMadeleine.new(persistence_base) { "hello" }
- madeleine.close
- assert_raises(RuntimeError) do
- madeleine.execute_command(Append.new("world"))
- end
- end
-end
-
-class NumberedFileTest < Test::Unit::TestCase
-
- def test_main
- target = Madeleine::NumberedFile.new(File::SEPARATOR + "foo", "bar", 321)
- assert_equal(File::SEPARATOR + "foo" + File::SEPARATOR +
- "000000000000000000321.bar",
- target.name)
- end
-end
-
-
-class LoggerTest < Test::Unit::TestCase
- include TestUtils
-
- def teardown
- delete_directory("whoah")
- end
-
- def test_creation
- @log = Object.new
- def @log.store(command)
- unless defined? @commands
- @commands = []
- end
- @commands << command
- end
- def @log.commands
- @commands
- end
-
- log_factory = self
- target = Madeleine::Logger.new("whoah", log_factory)
- target.store(:foo)
- assert(@log.commands.include?(:foo))
- end
-
- # Self-shunt
- def create_log(directory_name)
- @log
- end
-end
-
-class CommandVerificationTest < Test::Unit::TestCase
-
- def teardown
- Dir.delete("foo")
- end
-
- def test_broken_command
- target = SnapshotMadeleine.new("foo") { :a_system }
- assert_raises(Madeleine::InvalidCommandException) do
- target.execute_command(:not_a_command)
- end
- end
-end
-
-
-class CustomMarshallerTest < Test::Unit::TestCase
- include TestUtils
-
- def teardown
- delete_directory(prevalence_base)
- end
-
- def prevalence_base
- "custom-marshaller-test"
- end
-
- def madeleine_class
- SnapshotMadeleine
- end
-
- def test_changing_marshaller
- @log = ""
- marshaller = self
- target = madeleine_class.new(prevalence_base, marshaller) { "hello world" }
- target.take_snapshot
- assert_equal("dump ", @log)
- target = nil
-
- madeleine_class.new(prevalence_base, marshaller) { flunk() }
- assert_equal("dump load ", @log)
- end
-
- def load(io)
- @log << "load "
- assert_equal("dump data", io.read())
- end
-
- def dump(system, io)
- @log << "dump "
- assert_equal("hello world", system)
- io.write("dump data")
- end
-end
-
-
-class ErrorRaisingCommand
- def execute(system)
- raise "this is an exception from a command"
- end
-end
-
-class ErrorHandlingTest < Test::Unit::TestCase
- include TestUtils
-
- def teardown
- delete_directory(prevalence_base)
- end
-
- def prevalence_base
- "error-handling-base"
- end
-
- def test_exception_in_command
- madeleine = SnapshotMadeleine.new(prevalence_base) { "hello" }
- assert_raises(RuntimeError) do
- madeleine.execute_command(ErrorRaisingCommand.new)
- end
- madeleine.close
- madeleine = SnapshotMadeleine.new(prevalence_base) { "hello" }
- madeleine.close
- end
-end
-
-class QueryTest < Test::Unit::TestCase
- include TestUtils
-
- def teardown
- delete_directory(prevalence_base)
- end
-
- def prevalence_base
- "query-base"
- end
-
- def test_querying
- madeleine = SnapshotMadeleine.new(prevalence_base) { "hello" }
- query = Object.new
- def query.execute(system)
- system.size
- end
- # 'query' is an un-marshallable singleton, so we implicitly test
- # that querys aren't stored.
- assert_equal(5, madeleine.execute_query(query))
- # TODO: assert that no logging was done
- # TODO: assert that lock was held
- end
-end
-
-
-class TimeOptimizingLoggerTest < Test::Unit::TestCase
- include TestUtils
-
- def setup
- @target = Madeleine::Logger.new("some_directory", self)
- @log = []
- def @log.store(command)
- self << command
- end
- end
-
- def teardown
- delete_directory("some_directory")
- end
-
- def test_optimizing_ticks
- assert_equal(0, @log.size)
- @target.store(Madeleine::Clock::Tick.new(Time.at(3)))
- assert_equal(0, @log.size)
- @target.store(Madeleine::Clock::Tick.new(Time.at(22)))
- assert_equal(0, @log.size)
- @target.store(Addition.new(100))
- assert_kind_of(Madeleine::Clock::Tick, @log[0])
- assert_equal(22, value_of_tick(@log[0]))
- assert_equal(100, @log[1].value)
- assert_equal(2, @log.size)
- end
-
- def value_of_tick(tick)
- @clock = Object.new
- def @clock.forward_to(time)
- @value = time.to_i
- end
- def @clock.value
- @value
- end
- tick.execute(self)
- @clock.value
- end
-
- # Self-shunt
- def create_log(directory_name)
- assert_equal("some_directory", directory_name)
- @log
- end
-
- # Self-shunt
- def clock
- @clock
- end
-end
-
-
-class SharedLockQueryTest < Test::Unit::TestCase
- include TestUtils
-
- def prevalence_base
- "shared_lock_test"
- end
-
- def teardown
- delete_directory(prevalence_base)
- end
-
- def test_query
- madeleine = SnapshotMadeleine.new(prevalence_base) { "hello" }
- lock = Object.new
- madeleine.instance_eval { @lock = lock } # FIXME: The horror, the horror
-
- $shared = false
- $was_shared = false
- def lock.synchronize_shared(&block)
- $shared = true
- block.call
- $shared = false
- end
- query = Object.new
- def query.execute(system)
- $was_shared = $shared
- end
- madeleine.execute_query(query)
- assert($was_shared)
- end
-end
-
-suite = Test::Unit::TestSuite.new("Madeleine")
-
-suite << SnapshotMadeleineTest.suite
-suite << NumberedFileTest.suite
-require 'test_command_log'
-suite << CommandLogTest.suite
-suite << LoggerTest.suite
-suite << CommandVerificationTest.suite
-suite << CustomMarshallerTest.suite
-suite << ErrorHandlingTest.suite
-suite << QueryTest.suite
-suite << TimeOptimizingLoggerTest.suite
-suite << SharedLockQueryTest.suite
-require 'test_executer'
-suite << ExecuterTest.suite
-
-require 'test_clocked'
-add_clocked_tests(suite)
-require 'test_automatic'
-add_automatic_tests(suite)
-require 'test_persistence'
-add_persistence_tests(suite)
-require 'test_platforms'
-add_platforms_tests(suite)
-require 'test_zmarshal'
-add_zmarshal_tests(suite)
-
-require 'test/unit/ui/console/testrunner'
-Test::Unit::UI::Console::TestRunner.run(suite)
diff --git a/vendor/madeleine-0.7.1/test/test_automatic.rb b/vendor/madeleine-0.7.1/test/test_automatic.rb
deleted file mode 100755
index da0c1719..00000000
--- a/vendor/madeleine-0.7.1/test/test_automatic.rb
+++ /dev/null
@@ -1,559 +0,0 @@
-#!/usr/local/bin/ruby -w
-#
-# Copyright(c) 2003-2004 Stephen Sykes
-# Copyright(c) 2003-2004 Anders Bengtsson
-#
-
-$LOAD_PATH.unshift("lib")
-
-require 'madeleine'
-require 'madeleine/automatic'
-require 'test/unit'
-#require 'contrib/batched.rb' # uncomment if testing batched
-
-class A
- include Madeleine::Automatic::Interceptor
- attr_accessor :z,:k
- def initialize
- @k=1
- end
-end
-
-class B
- include Madeleine::Automatic::Interceptor
- attr_accessor :yy, :s
- def initialize(a)
- @yy = C.new(a)
- end
-end
-
-class C
- include Madeleine::Automatic::Interceptor
- attr_accessor :x, :a
- def initialize(x)
- @x = x
- @a ||= D.new
- end
-end
-
-# direct changes in this class are not saved, except at snapshot
-class D
- attr_accessor :w
-end
-
-class F
- include Madeleine::Automatic::Interceptor
- attr_accessor :z,:a
- def plus1
- @z += 1
- end
-end
-
-class G
- include Madeleine::Automatic::Interceptor
- attr_accessor :yy,:a
- def initialize
- @yy = H.new
- end
-end
-
-class H
- include Madeleine::Automatic::Interceptor
- attr_accessor :w
- def minus1
- @w -= 1
- end
-end
-
-class I
- include Madeleine::Automatic::Interceptor
- def initialize
- @x = J.new
- end
- def testyield
- r = false
- @x.yielder {|c| r = true if c == 1}
- r
- end
-end
-
-class J
- include Madeleine::Automatic::Interceptor
- def yielder
- yield 1
- end
-end
-
-class K
- include Madeleine::Automatic::Interceptor
- attr_accessor :k
- def initialize
- @k=1
- end
- def seven
- @k=7
- end
- def fourteen
- @k=14
- end
- automatic_read_only :fourteen
- automatic_read_only
- def twentyone
- @k=21
- end
-end
-
-class L
- include Madeleine::Automatic::Interceptor
- attr_reader :x
- def initialize
- @x = M.new(self)
- end
-end
-
-class M
- include Madeleine::Automatic::Interceptor
- attr_reader :yy
- def initialize(yy)
- @yy = yy
- end
-end
-
-class AutoTest < Test::Unit::TestCase
-
- def persister
- SnapshotMadeleine
- end
-
- def delete_directory(directory_name)
- return unless File.exist?(directory_name)
- Dir.foreach(directory_name) do |file|
- next if file == "."
- next if file == ".."
- assert(File.delete(directory_name + File::SEPARATOR + file) == 1,
- "Unable to delete #{file}")
- end
- Dir.delete(directory_name)
- end
-
- def create_new_system(klass, dir, *arg)
- delete_directory(dir)
- Thread.critical = true
- @system_bases << dir
- Thread.critical = false
- make_system(dir) { klass.new(*arg) }
- end
-
- def make_system(dir, marshaller=Marshal, &block)
- AutomaticSnapshotMadeleine.new(dir, marshaller, persister, &block)
- end
-
- def prevalence_base
- "AutoPrevalenceTestBase" + self.class.to_s
- end
-
- def setup
- @system_bases = []
- end
-
- def teardown
- @system_bases.each {|dir|
- delete_directory(dir)
- }
- end
-
- def simpletest(n)
- pb = prevalence_base + n.to_s
- mad_a = create_new_system(A, pb)
- mad_a.close
- mad_a1 = make_system(pb) { A.new }
- assert_equal(1, mad_a1.system.k, "No commands or snapshot")
- mad_a1.system.z = 0
- mad_a1.system.z += 1
- assert_equal(1, mad_a1.system.z, "Object changes")
- mad_a1.system.z -= 10
- assert_equal(-9, mad_a1.system.z, "Object changes")
- mad_a1.close
- mad_a2 = make_system(pb) { A.new }
- assert_equal(-9, mad_a2.system.z, "Commands but no snapshot")
- mad_a2.take_snapshot
- mad_a2.close
- mad_a3 = make_system(pb) { A.new }
- assert_equal(-9, mad_a3.system.z, "Snapshot but no commands")
- mad_a3.system.z -= 6
- mad_a3.system.z -= 3
- mad_a3.close
- mad_a4 = make_system(pb) { A.new }
- assert_equal(-18, mad_a4.system.z, "Snapshot and commands")
- mad_a4.close
- end
-end
-
-# Basic test, and that system works in SAFE level 1
-class BasicTest < AutoTest
- def test_main
- simpletest(1)
- end
-
- def test_main_in_safe_level_one
- thread = Thread.new {
- $SAFE = 1
- test_main
- }
- thread.join
- end
-end
-
-class ObjectOutsideTest < AutoTest
- def test_main
- mad = create_new_system(A, prevalence_base)
- assert_raises(RuntimeError) {
- mad.system.z = A.new # app object created outside system
- }
- mad.close
- end
-end
-
-# Passing a block when it would generate a command is not allowed because blocks cannot
-# be serialised. However, block passing/yielding inside the application is ok.
-class BlockGivenTest < AutoTest
- def test_main
- mad = create_new_system(J, prevalence_base)
- assert_raises(RuntimeError) {
- mad.system.yielder {|a| a}
- }
- mad.close
- mad2 = create_new_system(I, prevalence_base+"2")
- assert(mad2.system.testyield, "Internal block passing")
- mad2.close
- end
-end
-
-class NonPersistedObjectTest < AutoTest
- def test_main
- mad_b = create_new_system(B, prevalence_base, 0)
- mad_b.system.yy.x -= 1
- assert_equal(-1, mad_b.system.yy.x, "Direct change of object inside main object")
-
- mad_b.system.yy.a.w ||= "hello" # not saved
- mad_b.system.yy.a.w += " again" # not saved
-
- assert_equal("hello again", mad_b.system.yy.a.w, "Non persisted object before close")
-
- mad_b.close
- mad_b2 = make_system(prevalence_base) { B.new(0) }
- assert_equal(nil, mad_b2.system.yy.a.w, "Non persisted object after restart, no snapshot")
- mad_b2.system.yy.a.w ||= "hello" # not saved
- mad_b2.system.yy.a.w += " again" # not saved
- mad_b2.take_snapshot # NOW saved
- mad_b2.system.yy.a.w += " again" # not saved
- assert_equal("hello again again", mad_b2.system.yy.a.w, "Non persisted object after take_snapshot and 1 change")
-
- mad_b2.close
- mad_b3 = make_system(prevalence_base) { B.new(0) }
- assert_equal("hello again", mad_b3.system.yy.a.w, "Non persisted object after restore (back to snapshotted state)")
- mad_b3.close
- end
-end
-
-class RefInExternalObjTest < AutoTest
- def test_main
- mad_c = create_new_system(B, prevalence_base, 0)
- x = D.new
- x.w = mad_c.system.yy
- mad_c.system.s = x # pass in an external object that contains a ref to obj in ths system
-
- mad_c.system.s.w.x += 1 # Increment counter via external obj
- assert_equal(1, mad_c.system.yy.x, "Change via external object")
- mad_c.system.yy.x += 1 # Increment counter directly
- assert_equal(2, mad_c.system.s.w.x, "Direct change")
- mad_c.close
-
- mad_c2 = make_system(prevalence_base) { B.new(0) }
- assert_equal(2, mad_c2.system.s.w.x, "Value via external object after commands/restore")
- assert_equal(2, mad_c2.system.yy.x, "Direct value after restore")
- mad_c2.take_snapshot
- mad_c2.close
-
- mad_c3 = make_system(prevalence_base) { B.new(0) }
- assert_equal(2, mad_c3.system.s.w.x, "Value via external object after snapshot/restore")
- assert_equal(2, mad_c3.system.yy.x, "Direct value after snapshot/restore")
-
- mad_c3.system.s.w.x += 1 # Increment counter via external obj
- mad_c3.system.yy.x += 1 # Increment counter directly
- mad_c3.close
-
- mad_c4 = make_system(prevalence_base) { B.new(0) }
- assert_equal(4, mad_c4.system.s.w.x, "Value via external object after snapshot+commands/restore")
- assert_equal(4, mad_c4.system.yy.x, "Direct value after snapshot+commands/restore")
- mad_c4.close
- end
-end
-
-class BasicThreadSafetyTest < AutoTest
- def test_main
- x = Thread.new {
- simpletest(1)
- }
- y = Thread.new {
- simpletest(2)
- }
- x.join
- y.join
- end
-end
-
-class ThreadConfidenceTest < AutoTest
- def test_main
- mad_d = create_new_system(F, prevalence_base)
- mad_d.system.z = 0
- mad_e = create_new_system(G, prevalence_base+"2")
- mad_e.system.yy.w = 0
-
- x = []
- 25.times {|n|
- x[n] = Thread.new {
- 5.times {
- sleep(rand/10)
- mad_d.system.plus1
- mad_e.system.yy.minus1
- }
- }
- }
- 25.times {|n|
- x[n].join
- }
- assert_equal(125, mad_d.system.z, "125 commands")
- assert_equal(-125, mad_e.system.yy.w, "125 commands")
-
- mad_e.close
- mad_e2 = make_system(prevalence_base+"2") { G.new }
-
- 25.times {|n|
- x[n] = Thread.new {
- 5.times {
- sleep(rand/10)
- mad_d.system.plus1
- mad_e2.system.yy.minus1
- }
- }
- }
- 25.times {|n|
- x[n].join
- }
- assert_equal(250, mad_d.system.z, "restore/125 commands")
- assert_equal(-250, mad_e2.system.yy.w, "restore/125 commands")
- mad_d.close
- mad_e2.close
- end
-end
-
-class InvalidMethodTest < AutoTest
- def test_main
- mad_f = create_new_system(A, prevalence_base)
- mad_f.system.z = -1
- assert_raises(NoMethodError) {
- mad_f.system.not_a_method
- }
- assert_equal(-1, mad_f.system.z, "System functions after NoMethodError")
- mad_f.close
- end
-end
-
-class CircularReferenceTest < AutoTest
- def test_main
- mad_g = create_new_system(G, prevalence_base)
- mad_g.system.yy.w = mad_g.system
- mad_g.close
- mad_g2 = make_system(prevalence_base) { G.new }
- assert(mad_g2.system == mad_g2.system.yy.w.yy.w.yy.w, "Circular reference after command/restore")
- mad_g2.take_snapshot
- mad_g2.close
- mad_g3 = make_system(prevalence_base) { G.new }
- assert(mad_g3.system == mad_g3.system.yy.w.yy.w.yy.w, "Circular reference after snapshot/restore")
- mad_g3.system.yy.w.yy.w.yy.w.a = 1
- assert_equal(1, mad_g3.system.a, "Circular reference change")
- mad_g3.close
- mad_g4 = make_system(prevalence_base) { G.new }
- assert_equal(1, mad_g4.system.yy.w.yy.w.yy.w.a, "Circular reference after snapshot+commands/restore")
- mad_g4.close
-# The following tests would fail, cannot pass self (from class L to class M during init)
-# self is the proxied object itself, not the Prox object it needs to be
- mad_l = create_new_system(L, prevalence_base)
-# assert_equal(mad_l.system, mad_l.system.x.yy, "Circular ref before snapshot/restore, passed self")
- mad_l.take_snapshot
- mad_l.close
- mad_l = make_system(prevalence_base) { L.new }
-# assert_equal(mad_l.system, mad_l.system.x.yy, "Circular ref after snapshot/restore, passed self")
- mad_l.close
- end
-end
-
-class AutomaticCustomMarshallerTest < AutoTest
- def test_main
- custom_m(YAML)
- custom_m(SOAP::Marshal)
- custom_m(Madeleine::ZMarshal.new)
- custom_m(Madeleine::ZMarshal.new(YAML))
- custom_m(Madeleine::ZMarshal.new(SOAP::Marshal))
- end
-
- def custom_m(marshaller)
- dir = prevalence_base
- delete_directory(dir)
- @system_bases << dir
- mad_h = make_system(dir) { G.new }
- mad_h.system.yy.w = "abc"
- mad_h.take_snapshot
- mad_h.system.yy.w += "d"
- assert_equal("abcd", mad_h.system.yy.w, "Custom marshalling after snapshot+commands with normal marshaller")
- mad_h.close
- mad_h = make_system(dir, marshaller) { G.new }
- assert_equal("abcd", mad_h.system.yy.w, "Custom marshalling after snapshot+commands with normal marshaller, read with custom as marshaller")
- mad_h.close
- mad_h = make_system(dir) { G.new }
- mad_h.marshaller = marshaller
- mad_h.system.yy.w += "e"
- assert_equal("abcde", mad_h.system.yy.w, "Custom marshalling after snapshot+commands+change marshaller+commands")
- mad_h.take_snapshot
- mad_h.close
- if (marshaller == YAML)
- File.open(dir + "/000000000000000000002.snapshot", "r") {|f|
- assert_equal(f.gets, "--- !ruby/object:Madeleine::Automatic::Prox \n", "Custom marshalling marshaller change check")
- }
- end
- mad_h = make_system(dir, marshaller) { G.new }
- assert_equal("abcde", mad_h.system.yy.w,
- "Custom marshalling after snapshot+commands+change marshaller+commands+snapshot+restore with normal marshaller")
- mad_h.system.yy.w += "f"
- mad_h.close
- mad_h = make_system(dir) { G.new }
- assert_equal("abcdef", mad_h.system.yy.w, "Custom marshalling snapshot custom+commands+restore normal")
- mad_h.take_snapshot
- mad_h.close
- mad_h = make_system(dir, marshaller) { G.new }
- assert_equal("abcdef", mad_h.system.yy.w, "Custom marshalling snapshot+restore custom")
- mad_h.take_snapshot
- mad_h.system.yy.w += "g"
- mad_h.close
- mad_h = make_system(dir, marshaller) { G.new }
- assert_equal("abcdefg", mad_h.system.yy.w, "Custom marshalling after restore normal snapshot custom+commands+restore custom")
- mad_h.system.yy.w = "abc"
- mad_h.close
- mad_h2 = make_system(dir, marshaller) { G.new }
- assert_equal("abc", mad_h2.system.yy.w, "Custom marshalling after commands/restore")
- mad_h2.take_snapshot
- mad_h2.close
- mad_h3 = make_system(dir, marshaller) { G.new }
- assert_equal("abc", mad_h3.system.yy.w, "Custom marshalling after snapshot/restore")
- mad_h3.system.yy.w += "d"
- mad_h3.close
- mad_h4 = make_system(dir, marshaller) { G.new }
- assert_equal("abcd", mad_h4.system.yy.w, "Custom marshalling after snapshot+commands/restore")
- mad_h4.close
- mad_h = make_system(dir, marshaller) { G.new }
- mad_h.system.yy.w = mad_h.system
- mad_h.close
- mad_h2 = make_system(dir, marshaller) { G.new }
- assert_equal(mad_h2.system, mad_h2.system.yy.w, "Custom marshalling after commands/restore, circular ref")
- mad_h2.take_snapshot
- mad_h2.close
- mad_h3 = make_system(dir, marshaller) { G.new }
- assert_equal(mad_h3.system, mad_h3.system.yy.w, "Custom marshalling after snapshot/restore, circular ref")
- mad_h3.system.yy.w = "sss"
- mad_h3.system.yy.w = mad_h3.system
- mad_h3.close
- mad_h4 = make_system(dir, marshaller) { G.new }
- assert_equal(mad_h4.system, mad_h4.system.yy.w, "Custom marshalling after snapshot+commands/restore, circular ref")
- mad_h4.close
- end
-end
-
-# tests thread safety during system creation, particularly that different system ids are generated
-class ThreadedStartupTest < AutoTest
- def test_main
- x,mad = [],[]
- 20.times {|n|
- x[n] = Thread.new {
- sleep(rand/100)
- mad[n] = create_new_system(F, prevalence_base+n.to_s)
- mad[n].system.z = n
- assert_equal(n, mad[n].system.z, "object change mad[#{n}].z")
- mad[n].close
- }
- }
- 20.times {|n|
- x[n].join
- mad_i = make_system(prevalence_base+n.to_s) { F.new }
- assert_equal(n, mad_i.system.z, "restored mad[#{n}].z")
- mad_i.close
- }
- end
-end
-
-# tests restoring when objects get unreferenced and GC'd during restore
-class FinalisedTest < AutoTest
- def test_main
- mad = create_new_system(B, prevalence_base, 0)
- mad.system.yy = Array.new(200000) # make ruby run GC
- mad.system.yy = Array.new(200000) # must be a better way, but running GC.start from inside
- mad.system.yy = Array.new(50000) # class B didn't work for me
- mad.close
- mad2 = make_system(prevalence_base) { B.new(0) }
- mad2.close
- end
-end
-
-class DontInterceptTest < AutoTest
- def test_main
- mad = create_new_system(K, prevalence_base)
- mad.system.seven
- assert_equal(7, mad.system.k, "Object changes")
- mad.system.fourteen
- assert_equal(14, mad.system.k, "Object changes, not intercepted")
- mad.system.twentyone
- assert_equal(21, mad.system.k, "Object changes, not intercepted")
- mad.close
- mad_1 = make_system(prevalence_base) { K.new }
- assert_equal(7, mad_1.system.k, "Commands but no snapshot")
- mad_1.take_snapshot
- mad_1.close
- mad_2 = make_system(prevalence_base) { K.new }
- assert_equal(7, mad_2.system.k, "Snapshot but no commands")
- mad_2.system.k -= 6
- mad_2.system.k -= 3
- mad_2.system.fourteen
- mad_2.close
- mad_3 = make_system(prevalence_base) { K.new }
- assert_equal(-2, mad_3.system.k, "Snapshot and commands")
- mad_3.close
- end
-end
-
-def add_automatic_tests(suite)
- suite << BasicTest.suite
- suite << ObjectOutsideTest.suite
- suite << BlockGivenTest.suite
- suite << NonPersistedObjectTest.suite
- suite << RefInExternalObjTest.suite
- suite << InvalidMethodTest.suite
- suite << CircularReferenceTest.suite
- suite << BasicThreadSafetyTest.suite
- suite << FinalisedTest.suite
- suite << DontInterceptTest.suite
- suite << AutomaticCustomMarshallerTest.suite
-end
-
-def add_slow_automatic_tests(suite)
- suite << ThreadConfidenceTest.suite
- suite << ThreadedStartupTest.suite
-end
-
-if __FILE__ == $0
- slowsuite = Test::Unit::TestSuite.new("AutomaticMadeleine (including slow tests)")
- add_automatic_tests(slowsuite)
- add_slow_automatic_tests(slowsuite)
-
- require 'test/unit/ui/console/testrunner'
- Test::Unit::UI::Console::TestRunner.run(slowsuite)
-end
diff --git a/vendor/madeleine-0.7.1/test/test_clocked.rb b/vendor/madeleine-0.7.1/test/test_clocked.rb
deleted file mode 100755
index fcbd02d1..00000000
--- a/vendor/madeleine-0.7.1/test/test_clocked.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-
-require 'madeleine/clock'
-
-class ClockedAddingSystem
- include Madeleine::Clock::ClockedSystem
-
- attr_reader :total
-
- def initialize
- @total = 0
- end
-
- def add(value)
- @total += value
- @total
- end
-end
-
-class TimeTest < Test::Unit::TestCase
-
- def test_clock
- target = Madeleine::Clock::Clock.new
- assert_equal(0, target.time.to_i)
- assert_equal(0, target.time.usec)
-
- t1 = Time.at(10000)
- target.forward_to(t1)
- assert_equal(t1, target.time)
- t2 = Time.at(20000)
- target.forward_to(t2)
- assert_equal(t2, target.time)
-
- assert_nothing_raised() {
- target.forward_to(t2)
- }
- end
-
- def test_time_actor
- @forward_calls = 0
- @last_time = Time.at(0)
-
- target = Madeleine::Clock::TimeActor.launch(self, 0.01)
-
- # When launch() has returned it should have sent
- # one synchronous clock-tick before it went to sleep
- assert_equal(1, @forward_calls)
-
- sleep(0.1)
- assert(@forward_calls > 1)
- target.destroy
-
- @forward_calls = 0
- sleep(0.1)
- assert_equal(0, @forward_calls)
- end
-
- # Self-shunt
- def execute_command(command)
- mock_system = self
- command.execute(mock_system)
- end
-
- # Self-shunt (system)
- def clock
- self
- end
-
- # Self-shunt (clock)
- def forward_to(time)
- if time < @last_time
- raise "non-monotonous time"
- end
- @last_time = time
- @forward_calls += 1
- end
-
- def test_clocked_system
- target = Object.new
- target.extend(Madeleine::Clock::ClockedSystem)
- t1 = Time.at(10000)
- target.clock.forward_to(t1)
- assert_equal(t1, target.clock.time)
- t2 = Time.at(20000)
- target.clock.forward_to(t2)
- assert_equal(t2, target.clock.time)
- reloaded_target = Marshal.load(Marshal.dump(target))
- assert_equal(t2, reloaded_target.clock.time)
- end
-end
-
-
-def add_clocked_tests(suite)
- suite << TimeTest.suite
-end
diff --git a/vendor/madeleine-0.7.1/test/test_command_log.rb b/vendor/madeleine-0.7.1/test/test_command_log.rb
deleted file mode 100755
index 9f0961ca..00000000
--- a/vendor/madeleine-0.7.1/test/test_command_log.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-
-unless $LOAD_PATH.include?("lib")
- $LOAD_PATH.unshift("lib")
-end
-unless $LOAD_PATH.include?("test")
- $LOAD_PATH.unshift("test")
-end
-
-require 'madeleine'
-require 'test/unit'
-require 'stringio'
-
-class ExampleCommand
- attr :value
-
- def initialize(value)
- @value = value
- end
-
- def execute(system)
- system.add(@value)
- end
-end
-
-class CommandLogTest < Test::Unit::TestCase
-
- class MockFile < StringIO
- def fsync
- @was_fsynced = true
- super
- end
-
- attr :was_fsynced
- end
-
- def test_file_opening
- file_service = Object.new
- def file_service.exist?(path)
- [
- ["some", "path"].join(File::SEPARATOR),
- ["some", "path", "000000000000000000001.command_log"].join(File::SEPARATOR),
- ["some", "path", "000000000000000000002.command_log"].join(File::SEPARATOR),
- ["some", "path", "000000000000000000003.command_log"].join(File::SEPARATOR),
- ].include?(path)
- end
- def file_service.dir_entries(path, &block)
- if path != ["some", "path"].join(File::SEPARATOR)
- raise "wrong path"
- end
- [
- "000000000000000000001.command_log",
- "000000000000000000003.command_log",
- "000000000000000000002.command_log",
- ]
- end
- def file_service.open(path, flags)
- @was_open_called = true
- if path != ["some", "path", "000000000000000000004.command_log"].join(File::SEPARATOR)
- raise "wrong file id"
- end
- if flags != "wb"
- raise "wrong flags"
- end
- MockFile.new
- end
- def file_service.was_open_called
- @was_open_called
- end
-
- target = Madeleine::CommandLog.new("some/path", file_service)
- assert(file_service.was_open_called)
- end
-
- def test_writing_command
- file_service = Object.new
- def file_service.exist?(path)
- [
- ["some", "path"].join(File::SEPARATOR),
- ].include?(path)
- end
- def file_service.dir_entries(path, &block)
- if path != ["some", "path"].join(File::SEPARATOR)
- raise "wrong path"
- end
- []
- end
- def file_service.open(path, flags)
- @file = MockFile.new
- @file
- end
- def file_service.file
- @file
- end
- def file_service.verify
- unless @file.was_fsynced
- raise "file wasn't fsynced"
- end
- end
- command = ExampleCommand.new(1234)
-
- target = Madeleine::CommandLog.new("some/path", file_service)
- target.store(command)
-
- file_service.verify
-
- file_service.file.rewind
- assert_equal(Marshal.dump(command), file_service.file.read)
- end
-end
-
diff --git a/vendor/madeleine-0.7.1/test/test_executer.rb b/vendor/madeleine-0.7.1/test/test_executer.rb
deleted file mode 100755
index 27d2f062..00000000
--- a/vendor/madeleine-0.7.1/test/test_executer.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-
-unless $LOAD_PATH.include?("lib")
- $LOAD_PATH.unshift("lib")
-end
-unless $LOAD_PATH.include?("test")
- $LOAD_PATH.unshift("test")
-end
-
-require 'test/unit'
-require 'madeleine'
-
-class ExecuterTest < Test::Unit::TestCase
-
- def test_executer
- system = Object.new
- command = self
- executer = Madeleine::Executer.new(system)
- @executed_with = nil
- executer.execute(command)
- assert_same(system, @executed_with)
- end
-
- # Self-shunt
- def execute(system)
- @executed_with = system
- end
-
- def test_execute_with_exception
- system = Object.new
- command = Object.new
- def command.execute(system)
- raise "this is an exception from a command"
- end
- executer = Madeleine::Executer.new(system)
- assert_raises(RuntimeError) {
- executer.execute(command)
- }
- end
-
- def test_exception_in_recovery
- system = Object.new
- command = Object.new
- def command.execute(system)
- raise "this is an exception from a command"
- end
- executer = Madeleine::Executer.new(system)
- executer.recovery {
- executer.execute(command)
- }
- assert_raises(RuntimeError) {
- executer.execute(command)
- }
- end
-end
diff --git a/vendor/madeleine-0.7.1/test/test_persistence.rb b/vendor/madeleine-0.7.1/test/test_persistence.rb
deleted file mode 100755
index c0e3a639..00000000
--- a/vendor/madeleine-0.7.1/test/test_persistence.rb
+++ /dev/null
@@ -1,169 +0,0 @@
-#!/usr/local/bin/ruby -w
-#
-# Copyright(c) 2003 Anders Bengtsson
-#
-# PersistenceTest is based on the unit tests from Prevayler,
-# Copyright(c) 2001-2003 Klaus Wuestefeld.
-#
-
-$LOAD_PATH.unshift("lib")
-
-require 'madeleine'
-require 'test/unit'
-
-class AddingSystem
- attr_reader :total
-
- def initialize
- @total = 0
- end
-
- def add(value)
- @total += value
- @total
- end
-end
-
-
-class Addition
-
- attr_reader :value
-
- def initialize(value)
- @value = value
- end
-
- def execute(system)
- system.add(@value)
- end
-end
-
-
-class PersistenceTest < Test::Unit::TestCase
-
- def setup
- @madeleine = nil
- end
-
- def teardown
- delete_prevalence_files(prevalence_base)
- Dir.delete(prevalence_base)
- end
-
- def verify(expected_total)
- assert_equal(expected_total, prevalence_system().total(), "Total")
- end
-
- def prevalence_system
- @madeleine.system
- end
-
- def prevalence_base
- "PrevalenceBase"
- end
-
- def clear_prevalence_base
- @madeleine.close unless @madeleine.nil?
- delete_prevalence_files(prevalence_base())
- end
-
- def delete_prevalence_files(directory_name)
- return unless File.exist?(directory_name)
- Dir.foreach(directory_name) {|file_name|
- next if file_name == '.'
- next if file_name == '..'
- file_name.untaint
- assert(File.delete(directory_name + File::SEPARATOR + file_name) == 1,
- "Unable to delete #{file_name}")
- }
- end
-
- def crash_recover
- @madeleine.close unless @madeleine.nil?
- @madeleine = create_madeleine()
- end
-
- def create_madeleine
- SnapshotMadeleine.new(prevalence_base()) { AddingSystem.new }
- end
-
- def snapshot
- @madeleine.take_snapshot
- end
-
- def add(value, expected_total)
- total = @madeleine.execute_command(Addition.new(value))
- assert_equal(expected_total, total, "Total")
- end
-
- def verify_snapshots(expected_count)
- count = 0
- Dir.foreach(prevalence_base) {|name|
- if name =~ /\.snapshot$/
- count += 1
- end
- }
- assert_equal(expected_count, count, "snapshots")
- end
-
- def test_main
- clear_prevalence_base
-
- # There is nothing to recover at first.
- # A new system will be created.
- crash_recover
-
- crash_recover
- add(40,40)
- add(30,70)
- verify(70)
-
- crash_recover
- verify(70)
-
- add(20,90)
- add(15,105)
- verify_snapshots(0)
- snapshot
- verify_snapshots(1)
- snapshot
- verify_snapshots(2)
- verify(105)
-
- crash_recover
- snapshot
- add(10,115)
- snapshot
- add(5,120)
- add(4,124)
- verify(124)
-
- crash_recover
- add(3,127)
- verify(127)
-
- verify_snapshots(4)
-
- clear_prevalence_base
- snapshot
-
- crash_recover
- add(10,137)
- add(2,139)
- crash_recover
- verify(139)
- end
-
- def test_main_in_safe_level_one
- thread = Thread.new {
- $SAFE = 1
- test_main
- }
- thread.join
- end
-end
-
-
-def add_persistence_tests(suite)
- suite << PersistenceTest.suite
-end
diff --git a/vendor/madeleine-0.7.1/test/test_platforms.rb b/vendor/madeleine-0.7.1/test/test_platforms.rb
deleted file mode 100755
index b3ee03b1..00000000
--- a/vendor/madeleine-0.7.1/test/test_platforms.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-
-class AddCommand
- def initialize(obj)
- @obj = obj
- end
-
- def execute(system)
- system[@obj.myid] = @obj
- end
-end
-
-class Foo
- attr_accessor :myid
-end
-
-
-# Checks for a strange marshalling or IO bug observed in the
-# native win32-port of Ruby on WinXP.
-#
-# Test case provided by Steve Conover.
-
-class WierdWin32CorruptionTest < Test::Unit::TestCase
- include TestUtils
-
- def teardown
- (1..5).each {|i|
- delete_directory("corruption_test#{i}")
- }
- end
-
- def doCorruptionTest(idstr, storagenumber)
- m = SnapshotMadeleine.new("corruption_test" + storagenumber) { Hash.new() }
-
- f = Foo.new()
- f.myid = idstr
-
- m.execute_command(AddCommand.new(f))
- m.close()
- m = SnapshotMadeleine.new("corruption_test" + storagenumber) { Hash.new() }
- end
-
- def testErrorOne
- doCorruptionTest("123456789012345678901", "1")
- end
-
- def testErrorTwo
- doCorruptionTest("aaaaaaaaaaaaaaaaaaaaa", "2")
- end
-
- def testNoErrorOne
- doCorruptionTest("12345678901234567890", "3")
- end
-
- def testNoErrorTwo
- doCorruptionTest("1234567890123456789012", "4")
- end
-
- def testWhiteSpace
- doCorruptionTest("\n\r\t \r\n", "5")
- end
-end
-
-def add_platforms_tests(suite)
- suite << WierdWin32CorruptionTest.suite
-end
diff --git a/vendor/madeleine-0.7.1/test/test_zmarshal.rb b/vendor/madeleine-0.7.1/test/test_zmarshal.rb
deleted file mode 100755
index 80f46b90..00000000
--- a/vendor/madeleine-0.7.1/test/test_zmarshal.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-
-require 'madeleine/zmarshal'
-
-require 'stringio'
-require 'yaml'
-
-class ZMarshalTest < Test::Unit::TestCase
-
- def test_full_circle_marshal
- target = Madeleine::ZMarshal.new(Marshal)
- object = ["foo", "bar"]
- stream = StringIO.new
-
- target.dump(object, stream)
- stream.rewind
- result = target.load(stream)
-
- assert_equal(object, result)
- end
-
- def test_full_circle_yaml
- target = Madeleine::ZMarshal.new(YAML)
- object = ["foo", "bar"]
- stream = StringIO.new
-
- target.dump(object, stream)
- stream.rewind
- result = target.load(stream)
-
- assert_equal(object, result)
- end
-
- def test_compression
- target = Madeleine::ZMarshal.new(Marshal)
- object = "x" * 1000
-
- stream = StringIO.new
- Marshal.dump(object, stream)
- reference_size = stream.size
-
- stream = StringIO.new
- target.dump(object, stream)
- compressed_size = stream.size
-
- assert(compressed_size < reference_size)
- end
-end
-
-
-def add_zmarshal_tests(suite)
- suite << ZMarshalTest.suite
-end
From fa82bfdb9c5e3c8c26546983465764a096205cad Mon Sep 17 00:00:00 2001
From: Rick Okin
Date: Wed, 10 Aug 2005 05:58:18 +0000
Subject: [PATCH 18/84] Without Madeleine, chunks can again use their object_id
as a unique identifier, instead of an artificial one. This speeds up
rendering somewhat, and eliminates the last mention of Madeleine from the
codebase :)
---
lib/chunks/chunk.rb | 13 +++----------
lib/wiki_content.rb | 29 ++++++++++++-----------------
2 files changed, 15 insertions(+), 27 deletions(-)
diff --git a/lib/chunks/chunk.rb b/lib/chunks/chunk.rb
index 9ba3cc04..ad0fb148 100644
--- a/lib/chunks/chunk.rb
+++ b/lib/chunks/chunk.rb
@@ -27,8 +27,8 @@ module Chunk
# a regexp that matches all chunk_types masks
def Abstract::mask_re(chunk_types)
- tmp = chunk_types.map{|klass| klass.mask_string}.join("|")
- Regexp.new("chunk([0-9a-f]+n\\d+)(#{tmp})chunk")
+ chunk_classes = chunk_types.map{|klass| klass.mask_string}.join("|")
+ /chunk(\d+)(#{chunk_classes})chunk/
end
attr_reader :text, :unmask_text, :unmask_mode
@@ -53,14 +53,7 @@ module Chunk
# should contain only [a-z0-9]
def mask
- @mask ||="chunk#{@id}#{self.class.mask_string}chunk"
- end
-
- # We should not use object_id because object_id is not guarantied
- # to be unique when we restart the wiki (new object ids can equal old ones
- # that were restored from madeleine storage)
- def id
- @id ||= "#{@content.page_id}n#{@content.chunk_id}"
+ @mask ||= "chunk#{self.object_id}#{self.class.mask_string}chunk"
end
def unmask
diff --git a/lib/wiki_content.rb b/lib/wiki_content.rb
index dcc89ef9..6fcc4a85 100644
--- a/lib/wiki_content.rb
+++ b/lib/wiki_content.rb
@@ -59,14 +59,14 @@ module ChunkManager
def add_chunk(c)
@chunks_by_type[c.class] << c
- @chunks_by_id[c.id] = c
+ @chunks_by_id[c.object_id] = c
@chunks << c
@chunk_id += 1
end
def delete_chunk(c)
@chunks_by_type[c.class].delete(c)
- @chunks_by_id.delete(c.id)
+ @chunks_by_id.delete(c.object_id)
@chunks.delete(c)
end
@@ -82,18 +82,15 @@ module ChunkManager
@chunks.select { |chunk| chunk.kind_of?(chunk_type) and chunk.rendered? }
end
- # for testing and WikiContentStub; we need a page_id even if we have no page
- def page_id
- 0
- end
-
end
# A simplified version of WikiContent. Useful to avoid recursion problems in
# WikiContent.new
class WikiContentStub < String
+
attr_reader :options
include ChunkManager
+
def initialize(content, options)
super(content)
@options = options
@@ -167,7 +164,7 @@ class WikiContent < String
@options[:engine].apply_to(copy)
copy.inside_chunks(HIDE_CHUNKS) do |id|
- @chunks_by_id[id].revert
+ @chunks_by_id[id.to_i].revert
end
end
@@ -183,14 +180,16 @@ class WikiContent < String
pre_render!
@options[:engine].apply_to(self)
# unmask in one go. $~[1] is the chunk id
- gsub!(MASK_RE[ACTIVE_CHUNKS]){
- if chunk = @chunks_by_id[$~[1]]
- chunk.unmask_text
+ gsub!(MASK_RE[ACTIVE_CHUNKS]) do
+ chunk = @chunks_by_id[$~[1].to_i]
+ if chunk.nil?
# if we match a chunkmask that existed in the original content string
# just keep it as it is
- else
$~[0]
- end}
+ else
+ chunk.unmask_text
+ end
+ end
self
end
@@ -198,9 +197,5 @@ class WikiContent < String
@revision.page.name
end
- def page_id
- @revision.page.id
- end
-
end
From a91bd946b334f9b1ca3f092422fa9dbc6ae512ea Mon Sep 17 00:00:00 2001
From: Rick Okin
Date: Wed, 10 Aug 2005 05:59:42 +0000
Subject: [PATCH 19/84] Added db/*.db to svn:ignore
From 503aa99c636e695e9a226b9c42dcb47abeb12650 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Wed, 10 Aug 2005 06:16:15 +0000
Subject: [PATCH 20/84] Set default port to 2500
---
script/server | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/script/server b/script/server
index 487d1fd9..c6bdbb6f 100755
--- a/script/server
+++ b/script/server
@@ -4,9 +4,9 @@ require 'webrick'
require 'optparse'
OPTIONS = {
- :port => 3000,
+ :port => 2500,
:ip => "0.0.0.0",
- :environment => "development",
+ :environment => "production",
:server_root => File.expand_path(File.dirname(__FILE__) + "/../public/"),
:server_type => WEBrick::SimpleServer
}
@@ -18,8 +18,8 @@ ARGV.options do |opts|
opts.separator ""
opts.on("-p", "--port=port", Integer,
- "Runs Rails on the specified port.",
- "Default: 3000") { |OPTIONS[:port]| }
+ "Runs Instiki on the specified port.",
+ "Default: 2500") { |OPTIONS[:port]| }
opts.on("-b", "--binding=ip", String,
"Binds Rails to the specified ip.",
"Default: 0.0.0.0") { |OPTIONS[:ip]| }
@@ -44,6 +44,6 @@ require 'webrick_server'
OPTIONS['working_directory'] = File.expand_path(RAILS_ROOT)
-puts "=> Rails application started on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
-puts "=> Ctrl-C to shutdown server; call with --help for options" if OPTIONS[:server_type] == WEBrick::SimpleServer
+puts "=> Instiki started on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
+puts "=> Ctrl-C to shutdown; call with --help for options" if OPTIONS[:server_type] == WEBrick::SimpleServer
DispatchServlet.dispatch(OPTIONS)
From 50343b79e8fc57a5f40b89da0e11f2273bdd4b7c Mon Sep 17 00:00:00 2001
From: Ben Bleything
Date: Thu, 11 Aug 2005 05:36:35 +0000
Subject: [PATCH 21/84] Finish Rails-ifying the tree. Adds missing files and
directories and brings a few miscellaneous files up to date.
---
public/.htaccess | 11 +-
public/404.html | 2 +
public/500.html | 2 +
public/dispatch.cgi | 10 +
public/dispatch.fcgi | 24 +
public/favicon.ico | Bin 4710 -> 0 bytes
public/javascripts/controls.js | 446 ++++++++++
public/javascripts/dragdrop.js | 537 ++++++++++++
public/javascripts/effects.js | 612 ++++++++++++++
public/javascripts/prototype.js | 1374 +++++++++++++++++++++++--------
script/benchmarker | 19 +
script/destroy | 7 +
script/generate | 7 +
script/profiler | 34 +
script/runner | 29 +
15 files changed, 2776 insertions(+), 338 deletions(-)
create mode 100755 public/dispatch.cgi
create mode 100755 public/dispatch.fcgi
create mode 100644 public/javascripts/controls.js
create mode 100644 public/javascripts/dragdrop.js
create mode 100644 public/javascripts/effects.js
create mode 100755 script/benchmarker
create mode 100755 script/destroy
create mode 100755 script/generate
create mode 100755 script/profiler
create mode 100755 script/runner
diff --git a/public/.htaccess b/public/.htaccess
index bf245115..7eb56e8b 100644
--- a/public/.htaccess
+++ b/public/.htaccess
@@ -3,6 +3,13 @@ AddHandler fastcgi-script .fcgi
AddHandler cgi-script .cgi
Options +FollowSymLinks +ExecCGI
+# If you don't want Rails to look in certain directories,
+# use the following rewrite rules so that Apache won't rewrite certain requests
+#
+# Example:
+# RewriteCond %{REQUEST_URI} ^/notrails.*
+# RewriteRule .* - [L]
+
# Redirect all requests not available on the filesystem to Rails
# By default the cgi dispatcher is used which is very slow
#
@@ -14,7 +21,7 @@ RewriteEngine On
RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
-RewriteRule ^(.*)$ dispatch.cgi [QSA,L]
+RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
# In case Rails experiences terminal errors
# Instead of displaying this message you can supply a file here which will be rendered instead
@@ -22,4 +29,4 @@ RewriteRule ^(.*)$ dispatch.cgi [QSA,L]
# Example:
# ErrorDocument 500 /500.html
-ErrorDocument 500 "
Application error
Rails application failed to start properly"
\ No newline at end of file
+ErrorDocument 500 "
diff --git a/public/dispatch.cgi b/public/dispatch.cgi
new file mode 100755
index 00000000..3848806d
--- /dev/null
+++ b/public/dispatch.cgi
@@ -0,0 +1,10 @@
+#!/usr/bin/ruby1.8
+
+require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
+
+# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
+# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
+require "dispatcher"
+
+ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
+Dispatcher.dispatch
\ No newline at end of file
diff --git a/public/dispatch.fcgi b/public/dispatch.fcgi
new file mode 100755
index 00000000..3169ba26
--- /dev/null
+++ b/public/dispatch.fcgi
@@ -0,0 +1,24 @@
+#!/usr/bin/ruby1.8
+#
+# You may specify the path to the FastCGI crash log (a log of unhandled
+# exceptions which forced the FastCGI instance to exit, great for debugging)
+# and the number of requests to process before running garbage collection.
+#
+# By default, the FastCGI crash log is RAILS_ROOT/log/fastcgi.crash.log
+# and the GC period is nil (turned off). A reasonable number of requests
+# could range from 10-100 depending on the memory footprint of your app.
+#
+# Example:
+# # Default log path, normal GC behavior.
+# RailsFCGIHandler.process!
+#
+# # Default log path, 50 requests between GC.
+# RailsFCGIHandler.process! nil, 50
+#
+# # Custom log path, normal GC behavior.
+# RailsFCGIHandler.process! '/var/log/myapp_fcgi_crash.log'
+#
+require File.dirname(__FILE__) + "/../config/environment"
+require 'fcgi_handler'
+
+RailsFCGIHandler.process!
diff --git a/public/favicon.ico b/public/favicon.ico
index e61366585aa57740c9ca3d84a74e84be8f8bf3cb..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
GIT binary patch
literal 0
HcmV?d00001
literal 4710
zcmeHKA#WQo6n^LA*6Y%xIW%ct3#_=+D^TvygWaDpP%h_&(WeA?s+e{maV+0KG43`0fUjz~<)b}P%QRk>^R5$)m=b3K#b$IX2Cu)$vmaBr|6(lX^ULgXJdsDk?{xCvoOYjoqUpt44F}&;fA5RR
z^PB^wH=uSNwzFbBeoj31bwxS@IYCx!Om|;Qy-A->v^!tubMYKHoW+&k^r5NuWaF&!
z^_Ad^x8p)P3pgD2w#7a>TjVsqv}|+>iXUs(s#$Vb{*kQf|ul+sv2R%}}N&o-=
diff --git a/public/javascripts/controls.js b/public/javascripts/controls.js
new file mode 100644
index 00000000..cece0a91
--- /dev/null
+++ b/public/javascripts/controls.js
@@ -0,0 +1,446 @@
+// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Element.collectTextNodesIgnoreClass = function(element, ignoreclass) {
+ var children = $(element).childNodes;
+ var text = "";
+ var classtest = new RegExp("^([^ ]+ )*" + ignoreclass+ "( [^ ]+)*$","i");
+
+ for (var i = 0; i < children.length; i++) {
+ if(children[i].nodeType==3) {
+ text+=children[i].nodeValue;
+ } else {
+ if((!children[i].className.match(classtest)) && children[i].hasChildNodes())
+ text += Element.collectTextNodesIgnoreClass(children[i], ignoreclass);
+ }
+ }
+
+ return text;
+}
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getEntry(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: new Array (',', '\n') } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+var Autocompleter = {}
+Autocompleter.Base = function() {};
+Autocompleter.Base.prototype = {
+ base_initialize: function(element, update, options) {
+ this.element = $(element);
+ this.update = $(update);
+ this.has_focus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entry_count = 0;
+
+ if (this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = {}
+
+ this.options.tokens = this.options.tokens || new Array();
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.min_chars = this.options.min_chars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ var offsets = Position.cumulativeOffset(element);
+ update.style.left = offsets[0] + 'px';
+ update.style.top = (offsets[1] + element.offsetHeight) + 'px';
+ update.style.width = element.offsetWidth + 'px';
+ }
+ new Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(this.options.indicator)
+ this.indicator = $(this.options.indicator);
+
+ if (typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+
+ this.observer = null;
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(this.update.style.display=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix && (navigator.appVersion.indexOf('MSIE')>0) && this.update.style.position=='absolute') {
+ new Insertion.After(this.update,
+ '');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) {
+ Position.clone(this.update, this.iefix);
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ }
+ },
+
+ hide: function() {
+ if(this.update.style.display=='') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.indicator) Element.show(this.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.indicator) Element.hide(this.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.select_entry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.mark_previous();
+ this.render();
+ if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.mark_next();
+ this.render();
+ if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN)
+ return;
+
+ this.changed = true;
+ this.has_focus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.select_entry();
+ Event.stop(event);
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.has_focus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entry_count > 0) {
+ for (var i = 0; i < this.entry_count; i++)
+ this.index==i ?
+ Element.addClassName(this.get_entry(i),"selected") :
+ Element.removeClassName(this.get_entry(i),"selected");
+
+ if(this.has_focus) {
+ if(this.get_current_entry().scrollIntoView)
+ this.get_current_entry().scrollIntoView(false);
+
+ this.show();
+ this.active = true;
+ }
+ } else this.hide();
+ },
+
+ mark_previous: function() {
+ if(this.index > 0) this.index--
+ else this.index = this.entry_count-1;
+ },
+
+ mark_next: function() {
+ if(this.index < this.entry_count-1) this.index++
+ else this.index = 0;
+ },
+
+ get_entry: function(index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+ get_current_entry: function() {
+ return this.get_entry(this.index);
+ },
+
+ select_entry: function() {
+ this.active = false;
+ value = Element.collectTextNodesIgnoreClass(this.get_current_entry(), 'informal').unescapeHTML();
+ this.updateElement(value);
+ this.element.focus();
+ },
+
+ updateElement: function(value) {
+ var last_token_pos = this.findLastToken();
+ if (last_token_pos != -1) {
+ var new_value = this.element.value.substr(0, last_token_pos + 1);
+ var whitespace = this.element.value.substr(last_token_pos + 1).match(/^\s+/);
+ if (whitespace)
+ new_value += whitespace[0];
+ this.element.value = new_value + value;
+ } else {
+ this.element.value = value;
+ }
+ },
+
+ updateChoices: function(choices) {
+ if(!this.changed && this.has_focus) {
+ this.update.innerHTML = choices;
+ Element.cleanWhitespace(this.update);
+ Element.cleanWhitespace(this.update.firstChild);
+
+ if(this.update.firstChild && this.update.firstChild.childNodes) {
+ this.entry_count =
+ this.update.firstChild.childNodes.length;
+ for (var i = 0; i < this.entry_count; i++) {
+ entry = this.get_entry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entry_count = 0;
+ }
+
+ this.stopIndicator();
+
+ this.index = 0;
+ this.render();
+ }
+ },
+
+ addObservers: function(element) {
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+ },
+
+ onObserverEvent: function() {
+ this.changed = false;
+ if(this.getEntry().length>=this.options.min_chars) {
+ this.startIndicator();
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ getEntry: function() {
+ var token_pos = this.findLastToken();
+ if (token_pos != -1)
+ var ret = this.element.value.substr(token_pos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
+ else
+ var ret = this.element.value;
+
+ return /\n/.test(ret) ? '' : ret;
+ },
+
+ findLastToken: function() {
+ var last_token_pos = -1;
+
+ for (var i=0; i last_token_pos)
+ last_token_pos = this_token_pos;
+ }
+ return last_token_pos;
+ }
+}
+
+Ajax.Autocompleter = Class.create();
+Ajax.Autocompleter.prototype = Object.extend(new Autocompleter.Base(),
+Object.extend(new Ajax.Base(), {
+ initialize: function(element, update, url, options) {
+ this.base_initialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = this.onComplete.bind(this)
+ this.options.method = 'post';
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+ getUpdatedChoices: function() {
+ entry = encodeURIComponent(this.element.name) + '=' +
+ encodeURIComponent(this.getEntry());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if(this.options.defaultParams)
+ this.options.parameters += '&' + this.options.defaultParams;
+
+ new Ajax.Request(this.url, this.options);
+ },
+
+ onComplete: function(request) {
+ this.updateChoices(request.responseText);
+ }
+
+}));
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partial_search - If false, the autocompleter will match entered
+// text only at the beginning of strings in the
+// autocomplete array. Defaults to true, which will
+// match text at the beginning of any *word* in the
+// strings in the autocomplete array. If you want to
+// search anywhere in the string, additionally set
+// the option full_search to true (default: off).
+//
+// - full_search - Search anywhere in autocomplete array strings.
+//
+// - partial_chars - How many characters to enter before triggering
+// a partial match (unlike min_chars, which defines
+// how many characters are required to do any match
+// at all). Defaults to 2.
+//
+// - ignore_case - Whether to ignore case when autocompleting.
+// Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create();
+Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
+ initialize: function(element, update, array, options) {
+ this.base_initialize(element, update, options);
+ this.options.array = array;
+ },
+
+ getUpdatedChoices: function() {
+ this.updateChoices(this.options.selector(this));
+ },
+
+ setOptions: function(options) {
+ this.options = Object.extend({
+ choices: 10,
+ partial_search: true,
+ partial_chars: 2,
+ ignore_case: true,
+ full_search: false,
+ selector: function(instance) {
+ var ret = new Array(); // Beginning matches
+ var partial = new Array(); // Inside matches
+ var entry = instance.getEntry();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+ var elem = instance.options.array[i];
+ var found_pos = instance.options.ignore_case ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (found_pos != -1) {
+ if (found_pos == 0 && elem.length != entry.length) {
+ ret.push("
by <%= link_to_page(page.author) %>
- at <%= page.current_revision.pretty_created_on %>
+ at <%= format_date(page.revised_at) %>
<%= "from #{page.author.ip}" if page.author.respond_to?(:ip) %>
- <%= "Revision from #{@revision.pretty_created_on} by" %>
+ <%= "Revision from #{format_date(@revision.revised_at)} by" %>
<%= link_to_page @revision.author %>
From 61eacae836bcef5ab7928f0dfa0eed448dccd796 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Mon, 15 Aug 2005 00:07:43 +0000
Subject: [PATCH 31/84] Fix for exports and other file downloads
---
app/controllers/application.rb | 1 +
app/controllers/wiki_controller.rb | 1 +
2 files changed, 2 insertions(+)
diff --git a/app/controllers/application.rb b/app/controllers/application.rb
index 7f608e49..a126f845 100644
--- a/app/controllers/application.rb
+++ b/app/controllers/application.rb
@@ -63,6 +63,7 @@ class ApplicationController < ActionController::Base
def send_file(file, options = {})
options[:type] ||= (FILE_TYPES[File.extname(file)] || 'application/octet-stream')
+ options[:stream] = false
super(file, options)
end
diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb
index 81624733..d0b825bf 100644
--- a/app/controllers/wiki_controller.rb
+++ b/app/controllers/wiki_controller.rb
@@ -1,6 +1,7 @@
require 'fileutils'
require 'redcloth_for_tex'
require 'parsedate'
+require 'zip/zip'
class WikiController < ApplicationController
From 4849ca62fb0d317766c685471af99f3eac6810b6 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Mon, 15 Aug 2005 00:37:16 +0000
Subject: [PATCH 32/84] Fix for ticket:189
---
app/views/wiki/new.rhtml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/wiki/new.rhtml b/app/views/wiki/new.rhtml
index 0f46b5ad..d7202268 100644
--- a/app/views/wiki/new.rhtml
+++ b/app/views/wiki/new.rhtml
@@ -1,5 +1,5 @@
<%
- @title = "Creating #{WikiWords.separate(CGI.unescape(@page_name))}"
+ @title = "Creating #{WikiWords.separate(@page_name)}"
@content_width = 720
@hide_navigation = true
%>
From b29c59e4705a9de5c7be1de43cd726c3fc1d5a66 Mon Sep 17 00:00:00 2001
From: Ben Bleything
Date: Mon, 15 Aug 2005 19:17:32 +0000
Subject: [PATCH 33/84] Line ending cleanup. Most of these are svn propsets
which should make the files check out appropriately in the future. The three
files in app/models had inconsitent line endings, so they had to be fixed by
hand.
---
CHANGELOG | 372 ++++++++++-----------
README | 140 ++++----
app/models/page.rb | 272 ++++++++--------
app/models/revision.rb | 208 ++++++------
app/models/web.rb | 344 +++++++++----------
instiki.gemspec | 88 ++---
lib/db_structure.rb | 92 +++---
test/fixtures/pages.yml | 108 +++---
test/fixtures/revisions.yml | 166 +++++-----
test/fixtures/webs.yml | 28 +-
test/test_helper.rb | 212 ++++++------
test/unit/page_test.rb | 176 +++++-----
test/unit/revision_test.rb | 634 ++++++++++++++++++------------------
test/unit/web_test.rb | 316 +++++++++---------
14 files changed, 1578 insertions(+), 1578 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 96ba1c4f..519da063 100755
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,186 +1,186 @@
- * 0.10.2:
- Upgraded to Rails 0.13.1
- Fixed HTML export
- Added layout=no option to the export_html action (it exports page contents processed
- by the markup engine, but without the default layout - so that they can be wrapped in
- some other layout)
- tag can span several lines (before it was applied when both opening and closing
- tags were on the same line only)
- Resolved the "endless redirection loop" condition and otherwise improved handling of
- errors in the rendering engines
- Fixed rendering of Markdown hyperlinks such as [Text](http://something.com/foo)
-
- * 0.10.1:
- Upgraded Rails to 0.12.0
- Upgraded rubyzip to version 0.5.8
- BlueCloth is back (RedCloth didn't do pure Markdown well enough)
- Handling of line breaks in Textile is as in 0.9 (inserts tag)
- Fixed HTML export (to enclose the output in tags, include the stylesheet etc)
- Corrected some compatibility issues with storages from earlier Instiki versions
- Some other bug fixes
-
- * 0.10.0:
- Ported to ActionPack
- RedCloth 3.0.3
- BlueCloth is phased out, Markdown is rendered by RedCloth
- Mix markup option understands both Textile and Markdown on the same page
- Instiki can serve static content (such as HTML or plain-text files) from ./public
- directory
- Much friendlier admin interface
- Wiki link syntax doesn't conflict with Textile hyperlink syntax. Therefore
- "textile link":LinkToSomePlace will not look insane.
- RSS feeds accept query parameters, sush as
- http://localhost:2500/wiki/rss_with_headlines?start=2005-02-18&end=2005-02-19&limit=10
- RSS feed with page contents for a password-protected web behaves as follows:
- if the web is published, RSS feed links to the published version of the web
- otherwise, the feed is not available
- Madeleine will check every hour if there are new commands in the log or 24 hours have
- passed since last snapshot, and take snapshot if either of these conditions is true
- Madeleine will also not log read-only operations, resulting in a better performance
- Wiki extracts (to HTML and plain text) will leave only the last extract file in ./storage
- Wiki search handles multibyte (UTF-8) characters correctly
- Local hyperlinks in published pages point to published pages [Michael DeHaan]
- Fixed a bug that sometimes caused all past revisions of a page to be "forgotten" on
- restart
- Fixed parsing of URIs with a port number (http://someplace.org:8080)
- Instiki will not fork itself on a *nix, unless explicitly asked to
- Instiki can bind to IPs other than 127.0.0.1 (command-line option)
- Revisions that do not change anything on the page are rejected
- Automated tests for all controller actions
- category: lines are presented as links to "All Pages" for relevant categories
- Search looks at page titles, as well as content
- Multiple other usability enhancements and bug fixes
-
- * 0.9.2:
- Rollback takes the user to an edit form. The form has to be submitted for the change to
- take place.
- Changed to use inline style on published pages
- Fixed "forward in time" on the last revision before current page
- Instiki won't log bogus error messages when creating a new Wiki
- Fixed deprecation warning for Object.id (introduced in Ruby 1.8.2)
- Madeleine upgraded to 0.7.1
- Madeleine snapshots are compressed
- Packaged as a gem
-
- * 0.9.1:
- Added performance improvements for updating existing pages
- Fixed IP logging and RSS feeds behind proxies [With help from Guan Yang]
- Fixed default storage directory (borked running on Windows) [Spotted by Curt Hibbs]
-
- * 0.9.0:
- Added aliased links such as [[HomePage|that nice home page]] [Mark Reid]
- Added include other page content with [[!include TableOfContents]] [Mark Reid]
- Added delete orphan pages from the Edit Web screen [by inspiration from Simon Arnaud]
- Added logging of IP address for authors (who's behind the rollback wars)
- Added Categories pages through backlinks (use "categories: news, instiki" on start of line) [Mark Reid]
- Added option to use bracket-style wiki links only (and hence ban WikiWords)
- Added command-line option to specify different storage path
- Added print view without navigation
- Added character and page (2275 characters including spaces) counter (important for student papers)
- Off by default, activate it on the Edit Web screen
- Added LaTeX/PDF integration on Textile installations with pdflatex installed on system (EXPERIMENTAL)
- Use the home page as a table of contents with a unordered list to control sections
- Added limit of 15 to the number of pages included in RSS feed
- Moved static parts of stylesheet to separate file [Lau TŒrnskov]
- Fixed better semantics for revision movement [Ryan Singer]
- Fixed color diffs to work much better [Xen/Mertz/Atkins]
- Fixed performance problems for All Pages list [Dennis Mertz]
- Fixed lots of rendering bugs [Mark Reid]
- Upgraded to RedCloth 2.0.11 [integrating the fine work of Dennis Mertz]
-
- * 0.8.9:
- Added color diffs to see changes between revisions [Bill Atkins]
- They're aren't quite perfect yet as new paragraphs split the tags (hence 0.8.9, not 0.9.0)
- Added redirect to edit if content of page generates an error
- (so the page doesn't become unusable on bugs in the markup engines)
- Fixed update Web with different address bug [Denis Metz]
- Fixed a bunch of wiki word rendering issues by doing wiki word detection and replacment at once
- Upgraded to BlueCloth 0.0.3b (should fix loads of problems on Markdown wikis)
-
- * 0.8.5:
- Instiki can now serve as a CMS by running a password-protected web with a published front
- Added version check at startup (Instiki needs Ruby 1.8.1)
-
- * 0.8.1:
- Actually included RedCloth 2.0.7 in the release
-
- * 0.8.0:
- NOTE: Single-web wikis created in versions prior to 0.8.0 have "instiki" as their system password
- Accepts wiki words in bracket style. Ex: [[wiki word]], [[c]], [[We could'nt have done it!]]
- Accepts camel-case wiki words in all latin, greek, cyrillian, and armenian unicode characters
- Many thanks to Guan Yang for building the higher- and lower-case lookup tables
- And thanks to Simon Arnaud for the initial patch that got the work started
- Changed charset to UTF-8
- Cut down on command-line options and replaced them with an per-web config screen
- Added option to extend the stylesheet on a per-web basis to tweak the look in details
- Added simple color options for variety
- Added option to add/remove password protection on each web
- Added the wiki name of the author locking a given page (instead of just "someone")
- Removed single/multi-web distinction -- all Instikis are now multi-web
- Load libraries from an unshifted load path, so that old installed libraries doesn't clash [Emiel van de Laar]
- Keeps the author cookie forever, so you don't have to enter your name again and again
- Fixed XHTML so it validates [Bruce D'Arcus]
- Authors are no longer listed under orphan pages
- Added export to markup (great for backups, potentially for switching wiki engine)
- Don't link wiki words that proceeds from either /, = or ?
- (http://c2.com/cgi/wiki?WikiWikiClones, /show/HomePage, cgi.pl?show=WikiWord without escaping)
- Accessing an unexisting page redirects to a different url (/new/PageName)
- Increased snapshot time to just once a day (cuts down on disk storage requirements)
- Made RDoc support work better with 1.8.1 [Mauricio Fern‡ndez]
- Added convinient redirect from /wiki/ to /wiki/show/HomePage
- Fixed BlueCloth bug with backticks at start of line
- Updated to RedCloth 2.0.7 (and linked to the new Textile reference)
-
- * 0.7.0:
- Added Markdown (BlueCloth) and RDoc [Mauricio Fern‡ndez] as command-line markup choices
- Added wanted and orphan page lists to All pages (only show up if there's actually orphan or wanted pages)
- Added ISO-8859-1 as XML encoding in RSS feeds (makes FeedReader among others happy for special entities)
- Added proper links in the RSS feed (but the body links are still relative, which NNW and others doesn't grok)
- Added access keys: E => Edit, H => HomePage, A => All Pages, U => Recently Revised, X => Export
- Added password-login through URL (so you can subscribe to feed on a protected web)
- Added web passwords to the feed links for protected webs, so they work without manual login
- Added the web name in small letters above all pages within a web
- Polished authors and recently revised
- Updated to RedCloth 2.0.6
- Changed content type for RSS feeds to text/xml (makes Mozilla Aggreg8 happy)
- Changed searching to be case insensitive
- Changed HomePage to display the name of the web instead
- Changed exported HTML pages to be valid XHTML (which can be preprocessed by XSLT)
- Fixed broken recently revised
-
- * 0.6.0:
- Fixed Windows compatibility [Florian]
- Fixed bug that would prevent Madeleine from taking snapshots in Daemon mode
- Added export entire web as HTML in a zip file
- Added RSS feeds
- Added proper getops support for the growing number of options [Florian]
- Added safe mode that forbids style options in RedCloth [Florian]
- Updated RedCloth to 2.0.5
-
- * 0.5.0:
- NOTE: 0.5.0 is NOT compatible with databases from earlier versions
- Added revisions
- Added multiple webs
- Added password protection for webs on multi-web setups
- Added the notion of authors (that are saved in a cookie)
- Added command-line option for not running as a Daemon on Unix
-
- * 0.3.1:
- Added option to escape wiki words with \
-
- * 0.3.0:
- Brought all files into common style (including Textile help on the edit page)
- Added page locking (if someone already is editing a page there's a warning)
- Added daemon abilities on Unix (keep Instiki running after you close the terminal)
- Made port 2500 the default port, so Instiki can be launched by dobbelt-click
- Added Textile cache to speed-up rendering of large pages
- Made WikiWords look like "Wiki Words"
- Updated RedCloth to 2.0.4
-
- * 0.2.5:
- Upgraded to RedCloth 2.0.2 and Madeleine 0.6.1, which means the
- Windows problems are gone. Also fixed a problem with wikiwords
- that used part of other wikiwords.
-
- * 0.2.0:
- First public release
+ * 0.10.2:
+ Upgraded to Rails 0.13.1
+ Fixed HTML export
+ Added layout=no option to the export_html action (it exports page contents processed
+ by the markup engine, but without the default layout - so that they can be wrapped in
+ some other layout)
+ tag can span several lines (before it was applied when both opening and closing
+ tags were on the same line only)
+ Resolved the "endless redirection loop" condition and otherwise improved handling of
+ errors in the rendering engines
+ Fixed rendering of Markdown hyperlinks such as [Text](http://something.com/foo)
+
+ * 0.10.1:
+ Upgraded Rails to 0.12.0
+ Upgraded rubyzip to version 0.5.8
+ BlueCloth is back (RedCloth didn't do pure Markdown well enough)
+ Handling of line breaks in Textile is as in 0.9 (inserts tag)
+ Fixed HTML export (to enclose the output in tags, include the stylesheet etc)
+ Corrected some compatibility issues with storages from earlier Instiki versions
+ Some other bug fixes
+
+ * 0.10.0:
+ Ported to ActionPack
+ RedCloth 3.0.3
+ BlueCloth is phased out, Markdown is rendered by RedCloth
+ Mix markup option understands both Textile and Markdown on the same page
+ Instiki can serve static content (such as HTML or plain-text files) from ./public
+ directory
+ Much friendlier admin interface
+ Wiki link syntax doesn't conflict with Textile hyperlink syntax. Therefore
+ "textile link":LinkToSomePlace will not look insane.
+ RSS feeds accept query parameters, sush as
+ http://localhost:2500/wiki/rss_with_headlines?start=2005-02-18&end=2005-02-19&limit=10
+ RSS feed with page contents for a password-protected web behaves as follows:
+ if the web is published, RSS feed links to the published version of the web
+ otherwise, the feed is not available
+ Madeleine will check every hour if there are new commands in the log or 24 hours have
+ passed since last snapshot, and take snapshot if either of these conditions is true
+ Madeleine will also not log read-only operations, resulting in a better performance
+ Wiki extracts (to HTML and plain text) will leave only the last extract file in ./storage
+ Wiki search handles multibyte (UTF-8) characters correctly
+ Local hyperlinks in published pages point to published pages [Michael DeHaan]
+ Fixed a bug that sometimes caused all past revisions of a page to be "forgotten" on
+ restart
+ Fixed parsing of URIs with a port number (http://someplace.org:8080)
+ Instiki will not fork itself on a *nix, unless explicitly asked to
+ Instiki can bind to IPs other than 127.0.0.1 (command-line option)
+ Revisions that do not change anything on the page are rejected
+ Automated tests for all controller actions
+ category: lines are presented as links to "All Pages" for relevant categories
+ Search looks at page titles, as well as content
+ Multiple other usability enhancements and bug fixes
+
+ * 0.9.2:
+ Rollback takes the user to an edit form. The form has to be submitted for the change to
+ take place.
+ Changed to use inline style on published pages
+ Fixed "forward in time" on the last revision before current page
+ Instiki won't log bogus error messages when creating a new Wiki
+ Fixed deprecation warning for Object.id (introduced in Ruby 1.8.2)
+ Madeleine upgraded to 0.7.1
+ Madeleine snapshots are compressed
+ Packaged as a gem
+
+ * 0.9.1:
+ Added performance improvements for updating existing pages
+ Fixed IP logging and RSS feeds behind proxies [With help from Guan Yang]
+ Fixed default storage directory (borked running on Windows) [Spotted by Curt Hibbs]
+
+ * 0.9.0:
+ Added aliased links such as [[HomePage|that nice home page]] [Mark Reid]
+ Added include other page content with [[!include TableOfContents]] [Mark Reid]
+ Added delete orphan pages from the Edit Web screen [by inspiration from Simon Arnaud]
+ Added logging of IP address for authors (who's behind the rollback wars)
+ Added Categories pages through backlinks (use "categories: news, instiki" on start of line) [Mark Reid]
+ Added option to use bracket-style wiki links only (and hence ban WikiWords)
+ Added command-line option to specify different storage path
+ Added print view without navigation
+ Added character and page (2275 characters including spaces) counter (important for student papers)
+ Off by default, activate it on the Edit Web screen
+ Added LaTeX/PDF integration on Textile installations with pdflatex installed on system (EXPERIMENTAL)
+ Use the home page as a table of contents with a unordered list to control sections
+ Added limit of 15 to the number of pages included in RSS feed
+ Moved static parts of stylesheet to separate file [Lau TŒrnskov]
+ Fixed better semantics for revision movement [Ryan Singer]
+ Fixed color diffs to work much better [Xen/Mertz/Atkins]
+ Fixed performance problems for All Pages list [Dennis Mertz]
+ Fixed lots of rendering bugs [Mark Reid]
+ Upgraded to RedCloth 2.0.11 [integrating the fine work of Dennis Mertz]
+
+ * 0.8.9:
+ Added color diffs to see changes between revisions [Bill Atkins]
+ They're aren't quite perfect yet as new paragraphs split the tags (hence 0.8.9, not 0.9.0)
+ Added redirect to edit if content of page generates an error
+ (so the page doesn't become unusable on bugs in the markup engines)
+ Fixed update Web with different address bug [Denis Metz]
+ Fixed a bunch of wiki word rendering issues by doing wiki word detection and replacment at once
+ Upgraded to BlueCloth 0.0.3b (should fix loads of problems on Markdown wikis)
+
+ * 0.8.5:
+ Instiki can now serve as a CMS by running a password-protected web with a published front
+ Added version check at startup (Instiki needs Ruby 1.8.1)
+
+ * 0.8.1:
+ Actually included RedCloth 2.0.7 in the release
+
+ * 0.8.0:
+ NOTE: Single-web wikis created in versions prior to 0.8.0 have "instiki" as their system password
+ Accepts wiki words in bracket style. Ex: [[wiki word]], [[c]], [[We could'nt have done it!]]
+ Accepts camel-case wiki words in all latin, greek, cyrillian, and armenian unicode characters
+ Many thanks to Guan Yang for building the higher- and lower-case lookup tables
+ And thanks to Simon Arnaud for the initial patch that got the work started
+ Changed charset to UTF-8
+ Cut down on command-line options and replaced them with an per-web config screen
+ Added option to extend the stylesheet on a per-web basis to tweak the look in details
+ Added simple color options for variety
+ Added option to add/remove password protection on each web
+ Added the wiki name of the author locking a given page (instead of just "someone")
+ Removed single/multi-web distinction -- all Instikis are now multi-web
+ Load libraries from an unshifted load path, so that old installed libraries doesn't clash [Emiel van de Laar]
+ Keeps the author cookie forever, so you don't have to enter your name again and again
+ Fixed XHTML so it validates [Bruce D'Arcus]
+ Authors are no longer listed under orphan pages
+ Added export to markup (great for backups, potentially for switching wiki engine)
+ Don't link wiki words that proceeds from either /, = or ?
+ (http://c2.com/cgi/wiki?WikiWikiClones, /show/HomePage, cgi.pl?show=WikiWord without escaping)
+ Accessing an unexisting page redirects to a different url (/new/PageName)
+ Increased snapshot time to just once a day (cuts down on disk storage requirements)
+ Made RDoc support work better with 1.8.1 [Mauricio Fern‡ndez]
+ Added convinient redirect from /wiki/ to /wiki/show/HomePage
+ Fixed BlueCloth bug with backticks at start of line
+ Updated to RedCloth 2.0.7 (and linked to the new Textile reference)
+
+ * 0.7.0:
+ Added Markdown (BlueCloth) and RDoc [Mauricio Fern‡ndez] as command-line markup choices
+ Added wanted and orphan page lists to All pages (only show up if there's actually orphan or wanted pages)
+ Added ISO-8859-1 as XML encoding in RSS feeds (makes FeedReader among others happy for special entities)
+ Added proper links in the RSS feed (but the body links are still relative, which NNW and others doesn't grok)
+ Added access keys: E => Edit, H => HomePage, A => All Pages, U => Recently Revised, X => Export
+ Added password-login through URL (so you can subscribe to feed on a protected web)
+ Added web passwords to the feed links for protected webs, so they work without manual login
+ Added the web name in small letters above all pages within a web
+ Polished authors and recently revised
+ Updated to RedCloth 2.0.6
+ Changed content type for RSS feeds to text/xml (makes Mozilla Aggreg8 happy)
+ Changed searching to be case insensitive
+ Changed HomePage to display the name of the web instead
+ Changed exported HTML pages to be valid XHTML (which can be preprocessed by XSLT)
+ Fixed broken recently revised
+
+ * 0.6.0:
+ Fixed Windows compatibility [Florian]
+ Fixed bug that would prevent Madeleine from taking snapshots in Daemon mode
+ Added export entire web as HTML in a zip file
+ Added RSS feeds
+ Added proper getops support for the growing number of options [Florian]
+ Added safe mode that forbids style options in RedCloth [Florian]
+ Updated RedCloth to 2.0.5
+
+ * 0.5.0:
+ NOTE: 0.5.0 is NOT compatible with databases from earlier versions
+ Added revisions
+ Added multiple webs
+ Added password protection for webs on multi-web setups
+ Added the notion of authors (that are saved in a cookie)
+ Added command-line option for not running as a Daemon on Unix
+
+ * 0.3.1:
+ Added option to escape wiki words with \
+
+ * 0.3.0:
+ Brought all files into common style (including Textile help on the edit page)
+ Added page locking (if someone already is editing a page there's a warning)
+ Added daemon abilities on Unix (keep Instiki running after you close the terminal)
+ Made port 2500 the default port, so Instiki can be launched by dobbelt-click
+ Added Textile cache to speed-up rendering of large pages
+ Made WikiWords look like "Wiki Words"
+ Updated RedCloth to 2.0.4
+
+ * 0.2.5:
+ Upgraded to RedCloth 2.0.2 and Madeleine 0.6.1, which means the
+ Windows problems are gone. Also fixed a problem with wikiwords
+ that used part of other wikiwords.
+
+ * 0.2.0:
+ First public release
diff --git a/README b/README
index b5df8534..09d29a9f 100755
--- a/README
+++ b/README
@@ -1,70 +1,70 @@
-===What is Instiki?
-
-Admitted, it's YetAnotherWikiClone[http://c2.com/cgi/wiki?WikiWikiClones], but with a strong focus
-on simplicity of installation and running:
-
-Step 1. Download
-
-Step 2. Run "instiki"
-
-Step 3. Chuckle... "There's no step three!" (TM)
-
-You're now running a perfectly suitable wiki on port 2500
-that'll present you with one-step setup, followed by a textarea for the home page
-on http://localhost:2500.
-
-Instiki lowers the barriers of interest for when you might consider
-using a wiki. It's so simple to get running that you'll find yourself
-using it for anything -- taking notes, brainstorming, organizing a
-gathering.
-
-===Features:
-* Regular expression search: Find deep stuff really fast
-* Revisions: Follow the changes on every page from birth. Rollback to an earlier rev
-* Export to HTML or markup in a zip: Take the entire wiki with you home or for reference
-* RSS feeds to track recently revised pages
-* Multiple webs: Create separate wikis with their own namespace
-* Password-protected webs: Keep it private
-* Authors: Each revision is associated with an author, so you can see who changed what
-* Reference tracker: Which other pages are pointing to the current?
-* Speed: Using Madelein[http://madeleine.sourceforge.net] for persistence (all pages are in memory)
-* Three markup choices: Textile[http://www.textism.com/tools/textile]
- (default / RedCloth[http://www.whytheluckystiff.net/ruby/redcloth]),
- Markdown (BlueCloth[http://bluecloth.rubyforge.org]), and RDoc[http://rdoc.sourceforge.net/doc]
-* Embedded webserver: Through WEBrick[http://www.webrick.org]
-* Internationalization: Wiki words in any latin, greek, cyrillian, or armenian characters
-* Color diffs: Track changes through revisions
-
-===Missing:
-* File attachments
-
-===Install from gem:
-* Install rubygems
-* Run "gem install instiki"
-* Change to a directory where you want Instiki to keep its data files (for example, ~/instiki/)
-* Run "instiki" - this will create a "storage" directory (for example, ~/instiki/storage), and start a new Wiki service
-
-Make sure that you always launch Instiki from the same working directory, or specify the storage directory in runtime parameters, such as:
- instiki --storage ~/instiki/storage
-
-===Command-line options:
-* Run "instiki --help"
-
-===History:
- * See CHANGELOG
-
-===Download latest from:
-* http://rubyforge.org/project/showfiles.php?group_id=186
-
-===Visit the official Instiki wiki:
-* http://www.instiki.org
-
-===License:
-* same as Ruby's
-
----
-Author:: David Heinemeier Hansson
-Email:: david@loudthinking.com
-Weblog:: http://www.loudthinking.com
-
-
+===What is Instiki?
+
+Admitted, it's YetAnotherWikiClone[http://c2.com/cgi/wiki?WikiWikiClones], but with a strong focus
+on simplicity of installation and running:
+
+Step 1. Download
+
+Step 2. Run "instiki"
+
+Step 3. Chuckle... "There's no step three!" (TM)
+
+You're now running a perfectly suitable wiki on port 2500
+that'll present you with one-step setup, followed by a textarea for the home page
+on http://localhost:2500.
+
+Instiki lowers the barriers of interest for when you might consider
+using a wiki. It's so simple to get running that you'll find yourself
+using it for anything -- taking notes, brainstorming, organizing a
+gathering.
+
+===Features:
+* Regular expression search: Find deep stuff really fast
+* Revisions: Follow the changes on every page from birth. Rollback to an earlier rev
+* Export to HTML or markup in a zip: Take the entire wiki with you home or for reference
+* RSS feeds to track recently revised pages
+* Multiple webs: Create separate wikis with their own namespace
+* Password-protected webs: Keep it private
+* Authors: Each revision is associated with an author, so you can see who changed what
+* Reference tracker: Which other pages are pointing to the current?
+* Speed: Using Madelein[http://madeleine.sourceforge.net] for persistence (all pages are in memory)
+* Three markup choices: Textile[http://www.textism.com/tools/textile]
+ (default / RedCloth[http://www.whytheluckystiff.net/ruby/redcloth]),
+ Markdown (BlueCloth[http://bluecloth.rubyforge.org]), and RDoc[http://rdoc.sourceforge.net/doc]
+* Embedded webserver: Through WEBrick[http://www.webrick.org]
+* Internationalization: Wiki words in any latin, greek, cyrillian, or armenian characters
+* Color diffs: Track changes through revisions
+
+===Missing:
+* File attachments
+
+===Install from gem:
+* Install rubygems
+* Run "gem install instiki"
+* Change to a directory where you want Instiki to keep its data files (for example, ~/instiki/)
+* Run "instiki" - this will create a "storage" directory (for example, ~/instiki/storage), and start a new Wiki service
+
+Make sure that you always launch Instiki from the same working directory, or specify the storage directory in runtime parameters, such as:
+ instiki --storage ~/instiki/storage
+
+===Command-line options:
+* Run "instiki --help"
+
+===History:
+ * See CHANGELOG
+
+===Download latest from:
+* http://rubyforge.org/project/showfiles.php?group_id=186
+
+===Visit the official Instiki wiki:
+* http://www.instiki.org
+
+===License:
+* same as Ruby's
+
+---
+Author:: David Heinemeier Hansson
+Email:: david@loudthinking.com
+Weblog:: http://www.loudthinking.com
+
+
diff --git a/app/models/page.rb b/app/models/page.rb
index 8f2ef436..dfd5b87c 100644
--- a/app/models/page.rb
+++ b/app/models/page.rb
@@ -1,137 +1,137 @@
-class Page < ActiveRecord::Base
- belongs_to :web
- has_many :revisions, :order => 'id'
- has_one :current_revision, :class_name => 'Revision', :order => 'id DESC'
-
- def revise(content, time, author)
- revisions_size = new_record? ? 0 : revisions.size
- if (revisions_size > 0) and content == current_revision.content
- raise Instiki::ValidationError.new(
- "You have tried to save page '#{name}' without changing its content")
- end
-
- author = Author.new(author.to_s) unless author.is_a?(Author)
-
- # Try to render content to make sure that markup engine can take it,
- Revision.new(:page => self, :content => content, :author => author, :revised_at => time).force_rendering
-
- # A user may change a page, look at it and make some more changes - several times.
- # Not to record every such iteration as a new revision, if the previous revision was done
- # by the same author, not more than 30 minutes ago, then update the last revision instead of
- # creating a new one
- if (revisions_size > 0) && continous_revision?(time, author)
- current_revision.update_attributes(:content => content, :revised_at => time)
- else
- Revision.create(:page => self, :content => content, :author => author, :revised_at => time)
- end
-
- save
- web.refresh_pages_with_references(name) if revisions_size == 0
-
- self
- end
-
- def rollback(revision_number, time, author_ip = nil)
- roll_back_revision = self.revisions[revision_number]
- if roll_back_revision.nil?
- raise Instiki::ValidationError.new("Revision #{revision_number} not found")
- end
- revise(roll_back_revision.content, time, Author.new(roll_back_revision.author, author_ip))
- end
-
- def revisions?
- revisions.size > 1
- end
-
- def previous_revision(revision)
- revision_index = revisions.each_with_index do |rev, index|
- if rev.id == revision.id
- break index
- else
- nil
- end
- end
- if revision_index.nil? or revision_index == 0
- nil
- else
- revisions[revision_index - 1]
- end
- end
-
- def in_category?(cat)
- cat.nil? || cat.empty? || categories.include?(cat)
- end
-
- def categories
- display_content.find_chunks(Category).map { |cat| cat.list }.flatten
- end
-
- def authors
- revisions.collect { |rev| rev.author }
- end
-
- def references
- web.select.pages_that_reference(name)
- end
-
- def linked_from
- web.select.pages_that_link_to(name)
- end
-
- def included_from
- web.select.pages_that_include(name)
- end
-
- # Returns the original wiki-word name as separate words, so "MyPage" becomes "My Page".
- def plain_name
- web.brackets_only? ? name : WikiWords.separate(name)
- end
-
- # used to build chunk ids.
- #def id
- # @id ||= name.unpack('H*').first
- #end
-
- def link(options = {})
- web.make_link(name, nil, options)
- end
-
- def author_link(options = {})
- web.make_link(author, nil, options)
- end
-
- LOCKING_PERIOD = 30.minutes
-
- def lock(time, locked_by)
- update_attributes(:locked_at => time, :locked_by => locked_by)
- end
-
- def lock_duration(time)
- ((time - locked_at) / 60).to_i unless locked_at.nil?
- end
-
- def unlock
- update_attribute(:locked_at, nil)
- end
-
- def locked?(comparison_time)
- locked_at + LOCKING_PERIOD > comparison_time unless locked_at.nil?
- end
-
- private
-
- def continous_revision?(time, author)
- (current_revision.author == author) && (revised_at + 30.minutes > time)
- end
-
- # Forward method calls to the current revision, so the page responds to all revision calls
- def method_missing(method_id, *args, &block)
- method_name = method_id.to_s
- # Perform a hand-off to AR::Base#method_missing
- if @attributes.include?(method_name) or md = /(=|\?|_before_type_cast)$/.match(method_name)
- super(method_id, *args, &block)
- else
- current_revision.send(method_id)
- end
- end
+class Page < ActiveRecord::Base
+ belongs_to :web
+ has_many :revisions, :order => 'id'
+ has_one :current_revision, :class_name => 'Revision', :order => 'id DESC'
+
+ def revise(content, time, author)
+ revisions_size = new_record? ? 0 : revisions.size
+ if (revisions_size > 0) and content == current_revision.content
+ raise Instiki::ValidationError.new(
+ "You have tried to save page '#{name}' without changing its content")
+ end
+
+ author = Author.new(author.to_s) unless author.is_a?(Author)
+
+ # Try to render content to make sure that markup engine can take it,
+ Revision.new(:page => self, :content => content, :author => author, :revised_at => time).force_rendering
+
+ # A user may change a page, look at it and make some more changes - several times.
+ # Not to record every such iteration as a new revision, if the previous revision was done
+ # by the same author, not more than 30 minutes ago, then update the last revision instead of
+ # creating a new one
+ if (revisions_size > 0) && continous_revision?(time, author)
+ current_revision.update_attributes(:content => content, :revised_at => time)
+ else
+ Revision.create(:page => self, :content => content, :author => author, :revised_at => time)
+ end
+
+ save
+ web.refresh_pages_with_references(name) if revisions_size == 0
+
+ self
+ end
+
+ def rollback(revision_number, time, author_ip = nil)
+ roll_back_revision = self.revisions[revision_number]
+ if roll_back_revision.nil?
+ raise Instiki::ValidationError.new("Revision #{revision_number} not found")
+ end
+ revise(roll_back_revision.content, time, Author.new(roll_back_revision.author, author_ip))
+ end
+
+ def revisions?
+ revisions.size > 1
+ end
+
+ def previous_revision(revision)
+ revision_index = revisions.each_with_index do |rev, index|
+ if rev.id == revision.id
+ break index
+ else
+ nil
+ end
+ end
+ if revision_index.nil? or revision_index == 0
+ nil
+ else
+ revisions[revision_index - 1]
+ end
+ end
+
+ def in_category?(cat)
+ cat.nil? || cat.empty? || categories.include?(cat)
+ end
+
+ def categories
+ display_content.find_chunks(Category).map { |cat| cat.list }.flatten
+ end
+
+ def authors
+ revisions.collect { |rev| rev.author }
+ end
+
+ def references
+ web.select.pages_that_reference(name)
+ end
+
+ def linked_from
+ web.select.pages_that_link_to(name)
+ end
+
+ def included_from
+ web.select.pages_that_include(name)
+ end
+
+ # Returns the original wiki-word name as separate words, so "MyPage" becomes "My Page".
+ def plain_name
+ web.brackets_only? ? name : WikiWords.separate(name)
+ end
+
+ # used to build chunk ids.
+ #def id
+ # @id ||= name.unpack('H*').first
+ #end
+
+ def link(options = {})
+ web.make_link(name, nil, options)
+ end
+
+ def author_link(options = {})
+ web.make_link(author, nil, options)
+ end
+
+ LOCKING_PERIOD = 30.minutes
+
+ def lock(time, locked_by)
+ update_attributes(:locked_at => time, :locked_by => locked_by)
+ end
+
+ def lock_duration(time)
+ ((time - locked_at) / 60).to_i unless locked_at.nil?
+ end
+
+ def unlock
+ update_attribute(:locked_at, nil)
+ end
+
+ def locked?(comparison_time)
+ locked_at + LOCKING_PERIOD > comparison_time unless locked_at.nil?
+ end
+
+ private
+
+ def continous_revision?(time, author)
+ (current_revision.author == author) && (revised_at + 30.minutes > time)
+ end
+
+ # Forward method calls to the current revision, so the page responds to all revision calls
+ def method_missing(method_id, *args, &block)
+ method_name = method_id.to_s
+ # Perform a hand-off to AR::Base#method_missing
+ if @attributes.include?(method_name) or md = /(=|\?|_before_type_cast)$/.match(method_name)
+ super(method_id, *args, &block)
+ else
+ current_revision.send(method_id)
+ end
+ end
end
diff --git a/app/models/revision.rb b/app/models/revision.rb
index 9aab6370..56d818ce 100644
--- a/app/models/revision.rb
+++ b/app/models/revision.rb
@@ -1,105 +1,105 @@
-require 'diff'
-class Revision < ActiveRecord::Base
- belongs_to :page
- composed_of :author, :mapping => [ %w(author name), %w(ip ip) ]
-
- # Returns an array of all the WikiIncludes present in the content of this revision.
- def wiki_includes
- unless @wiki_includes_cache
- chunks = display_content.find_chunks(Include)
- @wiki_includes_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
- end
- @wiki_includes_cache
- end
-
- # Returns an array of all the WikiReferences present in the content of this revision.
- def wiki_references
- unless @wiki_references_cache
- chunks = display_content.find_chunks(WikiChunk::WikiReference)
- @wiki_references_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
- end
- @wiki_references_cache
- end
-
- # Returns an array of all the WikiWords present in the content of this revision.
- def wiki_words
- unless @wiki_words_cache
- wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
- @wiki_words_cache = wiki_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
- end
- @wiki_words_cache
- end
-
- # Returns an array of all the WikiWords present in the content of this revision.
- # that already exists as a page in the web.
- def existing_pages
- wiki_words.select { |wiki_word| page.web.page(wiki_word) }
- end
-
- # Returns an array of all the WikiWords present in the content of this revision
- # that *doesn't* already exists as a page in the web.
- def unexisting_pages
- wiki_words - existing_pages
- end
-
- # Explicit check for new type of display cache with chunks_by_type method.
- # Ensures new version works with older snapshots.
- def display_content
- unless @display_cache && @display_cache.respond_to?(:chunks_by_type)
- @display_cache = WikiContent.new(self)
- @display_cache.render!
- end
- @display_cache
- end
-
- # TODO this probably doesn't belong in revision (because it has to call back the page)
- def display_diff
- previous_revision = page.previous_revision(self)
- if previous_revision
- HTMLDiff.diff(previous_revision.display_content, display_content)
- else
- display_content
- end
- end
-
- def clear_display_cache
- @wiki_words_cache = @published_cache = @display_cache = @wiki_includes_cache =
- @wiki_references_cache = nil
- end
-
- def display_published
- unless @published_cache && @published_cache.respond_to?(:chunks_by_type)
- @published_cache = WikiContent.new(self, {:mode => :publish})
- @published_cache.render!
- end
- @published_cache
- end
-
- def display_content_for_export
- WikiContent.new(self, {:mode => :export} ).render!
- end
-
- def force_rendering
- begin
- display_content.render!
- rescue => e
- logger.error "Failed rendering page #{@name}"
- logger.error e
- message = e.message
- # substitute content with an error message
- self.content = <<-EOL
-
Markup engine has failed to render this page, raising the following error:
-
#{message}
-
#{self.content}
- EOL
- clear_display_cache
- raise e
- end
- end
-
- protected
-
- after_create :force_rendering
- after_save :clear_display_cache
-
+require 'diff'
+class Revision < ActiveRecord::Base
+ belongs_to :page
+ composed_of :author, :mapping => [ %w(author name), %w(ip ip) ]
+
+ # Returns an array of all the WikiIncludes present in the content of this revision.
+ def wiki_includes
+ unless @wiki_includes_cache
+ chunks = display_content.find_chunks(Include)
+ @wiki_includes_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
+ end
+ @wiki_includes_cache
+ end
+
+ # Returns an array of all the WikiReferences present in the content of this revision.
+ def wiki_references
+ unless @wiki_references_cache
+ chunks = display_content.find_chunks(WikiChunk::WikiReference)
+ @wiki_references_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
+ end
+ @wiki_references_cache
+ end
+
+ # Returns an array of all the WikiWords present in the content of this revision.
+ def wiki_words
+ unless @wiki_words_cache
+ wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
+ @wiki_words_cache = wiki_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
+ end
+ @wiki_words_cache
+ end
+
+ # Returns an array of all the WikiWords present in the content of this revision.
+ # that already exists as a page in the web.
+ def existing_pages
+ wiki_words.select { |wiki_word| page.web.page(wiki_word) }
+ end
+
+ # Returns an array of all the WikiWords present in the content of this revision
+ # that *doesn't* already exists as a page in the web.
+ def unexisting_pages
+ wiki_words - existing_pages
+ end
+
+ # Explicit check for new type of display cache with chunks_by_type method.
+ # Ensures new version works with older snapshots.
+ def display_content
+ unless @display_cache && @display_cache.respond_to?(:chunks_by_type)
+ @display_cache = WikiContent.new(self)
+ @display_cache.render!
+ end
+ @display_cache
+ end
+
+ # TODO this probably doesn't belong in revision (because it has to call back the page)
+ def display_diff
+ previous_revision = page.previous_revision(self)
+ if previous_revision
+ HTMLDiff.diff(previous_revision.display_content, display_content)
+ else
+ display_content
+ end
+ end
+
+ def clear_display_cache
+ @wiki_words_cache = @published_cache = @display_cache = @wiki_includes_cache =
+ @wiki_references_cache = nil
+ end
+
+ def display_published
+ unless @published_cache && @published_cache.respond_to?(:chunks_by_type)
+ @published_cache = WikiContent.new(self, {:mode => :publish})
+ @published_cache.render!
+ end
+ @published_cache
+ end
+
+ def display_content_for_export
+ WikiContent.new(self, {:mode => :export} ).render!
+ end
+
+ def force_rendering
+ begin
+ display_content.render!
+ rescue => e
+ logger.error "Failed rendering page #{@name}"
+ logger.error e
+ message = e.message
+ # substitute content with an error message
+ self.content = <<-EOL
+
Markup engine has failed to render this page, raising the following error:
+
#{message}
+
#{self.content}
+ EOL
+ clear_display_cache
+ raise e
+ end
+ end
+
+ protected
+
+ after_create :force_rendering
+ after_save :clear_display_cache
+
end
diff --git a/app/models/web.rb b/app/models/web.rb
index be520aba..13cb6f31 100644
--- a/app/models/web.rb
+++ b/app/models/web.rb
@@ -1,173 +1,173 @@
-require 'cgi'
-
-class Web < ActiveRecord::Base
- has_many :pages#, :include => [:current_revision, :web]
-
- def wiki
- Wiki.new
- end
-
- def file_yard
- @file_yard ||= FileYard.new("#{Wiki.storage_path}/#{address}", max_upload_size)
- end
-
- def settings_changed?(markup, safe_mode, brackets_only)
- self.markup != markup ||
- self.safe_mode != safe_mode ||
- self.brackets_only != brackets_only
- end
-
- def add_page(name, content, time, author)
- page = page(name) || Page.new(:web => self, :name => name)
- page.revise(content, time, author)
- end
-
- def authors
- select.authors
- end
-
- def categories
- select.map { |page| page.categories }.flatten.uniq.sort
- end
-
- def page(name)
- pages.find(:first, :conditions => ['name = ?', name])
- end
-
- def has_page?(name)
- Page.count(['web_id = ? AND name = ?', id, name]) > 0
- end
-
- def has_file?(name)
- wiki.file_yard(self).has_file?(name)
- end
-
- def markup
- read_attribute('markup').to_sym
- end
-
- def make_file_link(mode, name, text, base_url)
- link = CGI.escape(name)
- case mode
- when :export
- if has_file?(name) then "#{text}"
- else "#{text}" end
- when :publish
- if has_file?(name) then "#{text}"
- else "#{text}" end
- else
- if has_file?(name)
- "#{text}"
- else
- "#{text}?"
- end
- end
- end
-
- # Create a link for the given page name and link text based
- # on the render mode in options and whether the page exists
- # in the this web.
- # The links a relative, and will work only if displayed on another WikiPage.
- # It should not be used in menus, templates and such - instead, use link_to_page helper
- def make_link(name, text = nil, options = {})
- text = CGI.escapeHTML(text || WikiWords.separate(name))
- mode = options[:mode] || :show
- base_url = options[:base_url] || '..'
- link_type = options[:link_type] || :show
- case link_type.to_sym
- when :show
- make_page_link(mode, name, text, base_url)
- when :file
- make_file_link(mode, name, text, base_url)
- when :pic
- make_pic_link(mode, name, text, base_url)
- else
- raise "Unknown link type: #{link_type}"
- end
- end
-
- def make_page_link(mode, name, text, base_url)
- link = CGI.escape(name)
- case mode.to_sym
- when :export
- if has_page?(name) then %{#{text}}
- else %{#{text}} end
- when :publish
- if has_page?(name) then %{#{text}}
- else %{#{text}} end
- else
- if has_page?(name)
- %{#{text}}
- else
- %{#{text}?}
- end
- end
- end
-
- def make_pic_link(mode, name, text, base_url)
- link = CGI.escape(name)
- case mode.to_sym
- when :export
- if has_file?(name) then %{}
- else %{} end
- when :publish
- if has_file?(name) then %{}
- else %{#{text}} end
- else
- if has_file?(name) then %{}
- else %{#{text}?} end
- end
- end
-
- # Clears the display cache for all the pages with references to
- def refresh_pages_with_references(page_name)
- #select.pages_that_reference(page_name).each { |page|
- # page.revisions.each { |revision| revision.clear_display_cache }
- #}
- end
-
- def refresh_revisions
- select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
- end
-
- def remove_pages(pages_to_be_removed)
- pages_to_be_removed.each { |p| p.destroy }
- end
-
- def revised_at
- select.most_recent_revision
- end
-
- def select(&condition)
- PageSet.new(self, pages, condition)
- end
-
- private
-
- # Returns an array of all the wiki words in any current revision
- def wiki_words
- pages.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
- end
-
- # Returns an array of all the page names on this web
- def page_names
- pages.map { |p| p.name }
- end
-
- protected
- before_save :sanitize_markup
- before_validation :validate_address
- validates_uniqueness_of :address
- validates_length_of :color, :in => 3..6
-
- def sanitize_markup
- self.markup = markup.to_s
- end
-
- def validate_address
- unless address == CGI.escape(address)
- self.errors.add(:address, 'should contain only valid URI characters')
- raise Instiki::ValidationError.new("#{self.class.human_attribute_name('address')} #{errors.on(:address)}")
- end
- end
+require 'cgi'
+
+class Web < ActiveRecord::Base
+ has_many :pages#, :include => [:current_revision, :web]
+
+ def wiki
+ Wiki.new
+ end
+
+ def file_yard
+ @file_yard ||= FileYard.new("#{Wiki.storage_path}/#{address}", max_upload_size)
+ end
+
+ def settings_changed?(markup, safe_mode, brackets_only)
+ self.markup != markup ||
+ self.safe_mode != safe_mode ||
+ self.brackets_only != brackets_only
+ end
+
+ def add_page(name, content, time, author)
+ page = page(name) || Page.new(:web => self, :name => name)
+ page.revise(content, time, author)
+ end
+
+ def authors
+ select.authors
+ end
+
+ def categories
+ select.map { |page| page.categories }.flatten.uniq.sort
+ end
+
+ def page(name)
+ pages.find(:first, :conditions => ['name = ?', name])
+ end
+
+ def has_page?(name)
+ Page.count(['web_id = ? AND name = ?', id, name]) > 0
+ end
+
+ def has_file?(name)
+ wiki.file_yard(self).has_file?(name)
+ end
+
+ def markup
+ read_attribute('markup').to_sym
+ end
+
+ def make_file_link(mode, name, text, base_url)
+ link = CGI.escape(name)
+ case mode
+ when :export
+ if has_file?(name) then "#{text}"
+ else "#{text}" end
+ when :publish
+ if has_file?(name) then "#{text}"
+ else "#{text}" end
+ else
+ if has_file?(name)
+ "#{text}"
+ else
+ "#{text}?"
+ end
+ end
+ end
+
+ # Create a link for the given page name and link text based
+ # on the render mode in options and whether the page exists
+ # in the this web.
+ # The links a relative, and will work only if displayed on another WikiPage.
+ # It should not be used in menus, templates and such - instead, use link_to_page helper
+ def make_link(name, text = nil, options = {})
+ text = CGI.escapeHTML(text || WikiWords.separate(name))
+ mode = options[:mode] || :show
+ base_url = options[:base_url] || '..'
+ link_type = options[:link_type] || :show
+ case link_type.to_sym
+ when :show
+ make_page_link(mode, name, text, base_url)
+ when :file
+ make_file_link(mode, name, text, base_url)
+ when :pic
+ make_pic_link(mode, name, text, base_url)
+ else
+ raise "Unknown link type: #{link_type}"
+ end
+ end
+
+ def make_page_link(mode, name, text, base_url)
+ link = CGI.escape(name)
+ case mode.to_sym
+ when :export
+ if has_page?(name) then %{#{text}}
+ else %{#{text}} end
+ when :publish
+ if has_page?(name) then %{#{text}}
+ else %{#{text}} end
+ else
+ if has_page?(name)
+ %{#{text}}
+ else
+ %{#{text}?}
+ end
+ end
+ end
+
+ def make_pic_link(mode, name, text, base_url)
+ link = CGI.escape(name)
+ case mode.to_sym
+ when :export
+ if has_file?(name) then %{}
+ else %{} end
+ when :publish
+ if has_file?(name) then %{}
+ else %{#{text}} end
+ else
+ if has_file?(name) then %{}
+ else %{#{text}?} end
+ end
+ end
+
+ # Clears the display cache for all the pages with references to
+ def refresh_pages_with_references(page_name)
+ #select.pages_that_reference(page_name).each { |page|
+ # page.revisions.each { |revision| revision.clear_display_cache }
+ #}
+ end
+
+ def refresh_revisions
+ select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
+ end
+
+ def remove_pages(pages_to_be_removed)
+ pages_to_be_removed.each { |p| p.destroy }
+ end
+
+ def revised_at
+ select.most_recent_revision
+ end
+
+ def select(&condition)
+ PageSet.new(self, pages, condition)
+ end
+
+ private
+
+ # Returns an array of all the wiki words in any current revision
+ def wiki_words
+ pages.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
+ end
+
+ # Returns an array of all the page names on this web
+ def page_names
+ pages.map { |p| p.name }
+ end
+
+ protected
+ before_save :sanitize_markup
+ before_validation :validate_address
+ validates_uniqueness_of :address
+ validates_length_of :color, :in => 3..6
+
+ def sanitize_markup
+ self.markup = markup.to_s
+ end
+
+ def validate_address
+ unless address == CGI.escape(address)
+ self.errors.add(:address, 'should contain only valid URI characters')
+ raise Instiki::ValidationError.new("#{self.class.human_attribute_name('address')} #{errors.on(:address)}")
+ end
+ end
end
diff --git a/instiki.gemspec b/instiki.gemspec
index adf1dd74..c65ac414 100755
--- a/instiki.gemspec
+++ b/instiki.gemspec
@@ -1,44 +1,44 @@
-$__instiki_source_patterns = [
- '[A-Z]*', 'instiki', 'instiki.rb', 'app/**/*', 'lib/**/*', 'vendor/**/*',
- 'public/**/*', 'natives/**/*', 'config/**/*', 'script/**/*'
-]
-
-spec = Gem::Specification.new do |s|
- s.platform = Gem::Platform::RUBY
- s.name = 'instiki'
- s.version = "0.10.2"
- s.summary = 'Easy to install WikiClone running on WEBrick and SQLite'
- s.description = <<-EOF
- Instiki is a Wiki Clone written in Ruby that ships with an embedded
- webserver. You can setup up an Instiki in just a few steps.
- Possibly the simplest wiki setup ever.
- EOF
- s.author = 'David Heinemeier Hansson'
- s.email = 'david@loudthinking.com'
- s.rubyforge_project = 'instiki'
- s.homepage = 'http://www.instiki.org'
-
- s.bindir = '.'
- s.executables = ['instiki']
- s.default_executable = 'instiki'
-
- s.has_rdoc = false
-
- s.add_dependency('RedCloth', '= 3.0.3')
- s.add_dependency('rubyzip', '= 0.5.8')
- s.add_dependency('rails', '= 0.13.1')
- s.add_dependency('sqlite3-ruby', '= 1.1.0')
- s.requirements << 'none'
- s.require_path = 'lib'
-
- s.files = $__instiki_source_patterns.inject([]) { |list, glob|
- list << Dir[glob].delete_if { |path|
- File.directory?(path) or
- path.include?('.svn/') or
- path.include?('vendor/') or
- path.include?('test/') or
- path.include?('_test.rb')
- }
- }.flatten
-
-end
+$__instiki_source_patterns = [
+ '[A-Z]*', 'instiki', 'instiki.rb', 'app/**/*', 'lib/**/*', 'vendor/**/*',
+ 'public/**/*', 'natives/**/*', 'config/**/*', 'script/**/*'
+]
+
+spec = Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = 'instiki'
+ s.version = "0.10.2"
+ s.summary = 'Easy to install WikiClone running on WEBrick and SQLite'
+ s.description = <<-EOF
+ Instiki is a Wiki Clone written in Ruby that ships with an embedded
+ webserver. You can setup up an Instiki in just a few steps.
+ Possibly the simplest wiki setup ever.
+ EOF
+ s.author = 'David Heinemeier Hansson'
+ s.email = 'david@loudthinking.com'
+ s.rubyforge_project = 'instiki'
+ s.homepage = 'http://www.instiki.org'
+
+ s.bindir = '.'
+ s.executables = ['instiki']
+ s.default_executable = 'instiki'
+
+ s.has_rdoc = false
+
+ s.add_dependency('RedCloth', '= 3.0.3')
+ s.add_dependency('rubyzip', '= 0.5.8')
+ s.add_dependency('rails', '= 0.13.1')
+ s.add_dependency('sqlite3-ruby', '= 1.1.0')
+ s.requirements << 'none'
+ s.require_path = 'lib'
+
+ s.files = $__instiki_source_patterns.inject([]) { |list, glob|
+ list << Dir[glob].delete_if { |path|
+ File.directory?(path) or
+ path.include?('.svn/') or
+ path.include?('vendor/') or
+ path.include?('test/') or
+ path.include?('_test.rb')
+ }
+ }.flatten
+
+end
diff --git a/lib/db_structure.rb b/lib/db_structure.rb
index 09c212da..d92bb4e4 100644
--- a/lib/db_structure.rb
+++ b/lib/db_structure.rb
@@ -1,46 +1,46 @@
-require 'erb'
-
-def create_options
- if @db == 'mysql'
- 'ENGINE = ' + (mysql_engine rescue @mysql_engine)
- end
-end
-
-def db_quote(column)
- case @db
- when 'postgresql'
- return "\"#{column}\""
- when 'sqlite', 'sqlite3'
- return "'#{column}'"
- when 'mysql'
- return "`#{column}`"
- end
-end
-
-def db_structure(db)
- db.downcase!
- @db = db
- case db
- when 'postgresql'
- @pk = 'SERIAL PRIMARY KEY'
- @datetime = 'TIMESTAMP'
- @boolean = "BOOLEAN"
- when 'sqlite', 'sqlite3'
- @pk = 'INTEGER PRIMARY KEY'
- @datetime = 'DATETIME'
- @boolean = "INTEGER"
- when 'mysql'
- @pk = 'INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY'
- @datetime = 'DATETIME'
- @boolean = "TINYINT"
- @mysql_engine = 'InnoDB'
- else
- raise "Unknown db type #{db}"
- end
-
- s = ''
- Dir[RAILS_ROOT + '/db/*.erbsql'].each do |filename|
- s += ERB.new(File.read(filename)).result
- end
- s
-end
+require 'erb'
+
+def create_options
+ if @db == 'mysql'
+ 'ENGINE = ' + (mysql_engine rescue @mysql_engine)
+ end
+end
+
+def db_quote(column)
+ case @db
+ when 'postgresql'
+ return "\"#{column}\""
+ when 'sqlite', 'sqlite3'
+ return "'#{column}'"
+ when 'mysql'
+ return "`#{column}`"
+ end
+end
+
+def db_structure(db)
+ db.downcase!
+ @db = db
+ case db
+ when 'postgresql'
+ @pk = 'SERIAL PRIMARY KEY'
+ @datetime = 'TIMESTAMP'
+ @boolean = "BOOLEAN"
+ when 'sqlite', 'sqlite3'
+ @pk = 'INTEGER PRIMARY KEY'
+ @datetime = 'DATETIME'
+ @boolean = "INTEGER"
+ when 'mysql'
+ @pk = 'INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY'
+ @datetime = 'DATETIME'
+ @boolean = "TINYINT"
+ @mysql_engine = 'InnoDB'
+ else
+ raise "Unknown db type #{db}"
+ end
+
+ s = ''
+ Dir[RAILS_ROOT + '/db/*.erbsql'].each do |filename|
+ s += ERB.new(File.read(filename)).result
+ end
+ s
+end
diff --git a/test/fixtures/pages.yml b/test/fixtures/pages.yml
index f7add425..65fba487 100644
--- a/test/fixtures/pages.yml
+++ b/test/fixtures/pages.yml
@@ -1,55 +1,55 @@
-home_page:
- id: 1
- created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
- updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
- web_id: 1
- name: HomePage
-
-my_way:
- id: 2
- created_at: <%= 9.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
- web_id: 1
- name: MyWay
-
-smart_engine:
- id: 3
- created_at: <%= 8.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
- web_id: 1
- name: SmartEngine
-
-that_way:
- id: 4
- created_at: <%= 7.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
- web_id: 1
- name: ThatWay
-
-no_wiki_word:
- id: 5
- created_at: <%= 6.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
- web_id: 1
- name: NoWikiWord
-
-first_page:
- id: 6
- created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
- updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
- web_id: 1
- name: FirstPage
-
-oak:
- id: 7
- created_at: <%= 5.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
- web_id: 1
- name: Oak
-
-elephant:
- id: 8
- created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
- updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
- web_id: 1
+home_page:
+ id: 1
+ created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
+ updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
+ web_id: 1
+ name: HomePage
+
+my_way:
+ id: 2
+ created_at: <%= 9.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
+ web_id: 1
+ name: MyWay
+
+smart_engine:
+ id: 3
+ created_at: <%= 8.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
+ web_id: 1
+ name: SmartEngine
+
+that_way:
+ id: 4
+ created_at: <%= 7.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
+ web_id: 1
+ name: ThatWay
+
+no_wiki_word:
+ id: 5
+ created_at: <%= 6.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
+ web_id: 1
+ name: NoWikiWord
+
+first_page:
+ id: 6
+ created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
+ updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
+ web_id: 1
+ name: FirstPage
+
+oak:
+ id: 7
+ created_at: <%= 5.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
+ web_id: 1
+ name: Oak
+
+elephant:
+ id: 8
+ created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
+ updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
+ web_id: 1
name: Elephant
\ No newline at end of file
diff --git a/test/fixtures/revisions.yml b/test/fixtures/revisions.yml
index 77585e99..d65c2bd2 100644
--- a/test/fixtures/revisions.yml
+++ b/test/fixtures/revisions.yml
@@ -1,83 +1,83 @@
-home_page_first_revision:
- id: 1
- created_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
- updated_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
- revised_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
- page_id: 1
- content: First revision of the HomePage end
- author: AnAuthor
- ip: 127.0.0.1
-
-my_way_first_revision:
- id: 2
- created_at: <%= 9.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
- revised_at: <%= 9.days.ago.to_formatted_s(:db) %>
- page_id: 2
- content: MyWay
- author: Me
-
-smart_engine_first_revision:
- id: 3
- created_at: <%= 8.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
- revised_at: <%= 8.days.ago.to_formatted_s(:db) %>
- page_id: 3
- content: SmartEngine
- author: Me
-
-that_way_first_revision:
- id: 4
- created_at: <%= 7.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
- revised_at: <%= 7.days.ago.to_formatted_s(:db) %>
- page_id: 4
- content: ThatWay
- author: Me
-
-no_wiki_word_first_revision:
- id: 5
- created_at: <%= 6.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
- revised_at: <%= 6.days.ago.to_formatted_s(:db) %>
- page_id: 5
- content: hey you
- author: Me
-
-home_page_second_revision:
- id: 6
- created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
- updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
- revised_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
- page_id: 1
- content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \OverThere -- see SmartEngine in that SmartEngineGUI
- author: DavidHeinemeierHansson
-
-first_page_first_revision:
- id: 7
- created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
- updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
- revised_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
- page_id: 6
- content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\OverThere -- see SmartEngine in that SmartEngineGUI
- author: DavidHeinemeierHansson
-
-oak_first_revision:
- id: 8
- created_at: <%= 5.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
- revised_at: <%= 5.days.ago.to_formatted_s(:db) %>
- page_id: 7
- content: "All about oak.\ncategory: trees"
- author: TreeHugger
- ip: 127.0.0.2
-
-elephant_first_revision:
- id: 9
- created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
- updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
- revised_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
- page_id: 8
- content: "All about elephants.\ncategory: animals"
- author: Guest
- ip: 127.0.0.2
+home_page_first_revision:
+ id: 1
+ created_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
+ updated_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
+ revised_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
+ page_id: 1
+ content: First revision of the HomePage end
+ author: AnAuthor
+ ip: 127.0.0.1
+
+my_way_first_revision:
+ id: 2
+ created_at: <%= 9.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
+ revised_at: <%= 9.days.ago.to_formatted_s(:db) %>
+ page_id: 2
+ content: MyWay
+ author: Me
+
+smart_engine_first_revision:
+ id: 3
+ created_at: <%= 8.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
+ revised_at: <%= 8.days.ago.to_formatted_s(:db) %>
+ page_id: 3
+ content: SmartEngine
+ author: Me
+
+that_way_first_revision:
+ id: 4
+ created_at: <%= 7.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
+ revised_at: <%= 7.days.ago.to_formatted_s(:db) %>
+ page_id: 4
+ content: ThatWay
+ author: Me
+
+no_wiki_word_first_revision:
+ id: 5
+ created_at: <%= 6.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
+ revised_at: <%= 6.days.ago.to_formatted_s(:db) %>
+ page_id: 5
+ content: hey you
+ author: Me
+
+home_page_second_revision:
+ id: 6
+ created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
+ updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
+ revised_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
+ page_id: 1
+ content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \OverThere -- see SmartEngine in that SmartEngineGUI
+ author: DavidHeinemeierHansson
+
+first_page_first_revision:
+ id: 7
+ created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
+ updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
+ revised_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
+ page_id: 6
+ content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\OverThere -- see SmartEngine in that SmartEngineGUI
+ author: DavidHeinemeierHansson
+
+oak_first_revision:
+ id: 8
+ created_at: <%= 5.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
+ revised_at: <%= 5.days.ago.to_formatted_s(:db) %>
+ page_id: 7
+ content: "All about oak.\ncategory: trees"
+ author: TreeHugger
+ ip: 127.0.0.2
+
+elephant_first_revision:
+ id: 9
+ created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
+ updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
+ revised_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
+ page_id: 8
+ content: "All about elephants.\ncategory: animals"
+ author: Guest
+ ip: 127.0.0.2
diff --git a/test/fixtures/webs.yml b/test/fixtures/webs.yml
index 29c89566..05437295 100644
--- a/test/fixtures/webs.yml
+++ b/test/fixtures/webs.yml
@@ -1,15 +1,15 @@
-test_wiki:
- id: 1
- created_at: 2004-08-01
- updated_at: 2005-08-01
- name: wiki1
- address: wiki1
- markup: textile
-
-instiki:
- id: 2
- created_at: 2004-08-01
- updated_at: 2005-08-01
- name: Instiki
- address: instiki
+test_wiki:
+ id: 1
+ created_at: 2004-08-01
+ updated_at: 2005-08-01
+ name: wiki1
+ address: wiki1
+ markup: textile
+
+instiki:
+ id: 2
+ created_at: 2004-08-01
+ updated_at: 2005-08-01
+ name: Instiki
+ address: instiki
markup: textile
\ No newline at end of file
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 0b29f757..955b059e 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -1,106 +1,106 @@
-ENV["RAILS_ENV"] = "test"
-
-# Expand the path to environment so that Ruby does not load it multiple times
-# File.expand_path can be removed if Ruby 1.9 is in use.
-require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
-require 'application'
-
-require 'test/unit'
-require 'active_record/fixtures'
-require 'action_controller/test_process'
-require 'action_web_service/test_invoke'
-require 'breakpoint'
-require 'wiki_content'
-
-# Uncomment these and hang on, because the tests will be FAST
-#Test::Unit::TestCase.pre_loaded_fixtures = false
-#Test::Unit::TestCase.use_transactional_fixtures = true
-
-Test::Unit::TestCase.use_instantiated_fixtures = false
-Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
-
-class Test::Unit::TestCase
- def create_fixtures(*table_names)
- Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures", table_names)
- end
-
- # Add more helper methods to be used by all tests here...
- def set_web_property(property, value)
- @web.update_attribute(property, value)
- @page = Page.find(@page.id)
- @wiki.webs[@web.name] = @web
- end
-
- def setup_wiki_with_30_pages
- ActiveRecord::Base.silence do
- (1..30).each do |i|
- @wiki.write_page('wiki1', "page#{i}", "Test page #{i}\ncategory: test",
- Time.local(1976, 10, i, 12, 00, 00), Author.new('Dema', '127.0.0.2'))
- end
- end
- @web = Web.find(@web.id)
- end
-
- def use_blank_wiki
- Revision.destroy_all
- Page.destroy_all
- Web.destroy_all
- end
-end
-
-# This module is to be included in unit tests that involve matching chunks.
-# It provides a easy way to test whether a chunk matches a particular string
-# and any the values of any fields that should be set after a match.
-class ContentStub < String
- include ChunkManager
- def initialize(str)
- super
- init_chunk_manager
- end
- def page_link(*); end
-end
-
-module ChunkMatch
-
- # Asserts a number of tests for the given type and text.
- def match(chunk_type, test_text, expected_chunk_state)
- if chunk_type.respond_to? :pattern
- assert_match(chunk_type.pattern, test_text)
- end
-
- content = ContentStub.new(test_text)
- chunk_type.apply_to(content)
-
- # Test if requested parts are correct.
- expected_chunk_state.each_pair do |a_method, expected_value|
- assert content.chunks.last.kind_of?(chunk_type)
- assert_respond_to(content.chunks.last, a_method)
- assert_equal(expected_value, content.chunks.last.send(a_method.to_sym),
- "Wrong #{a_method} value")
- end
- end
-
- # Asserts that test_text doesn't match the chunk_type
- def no_match(chunk_type, test_text)
- if chunk_type.respond_to? :pattern
- assert_no_match(chunk_type.pattern, test_text)
- end
- end
-end
-
-if defined? $validate_xml_in_assert_success and $validate_xml_in_assert_success == true
- module Test
- module Unit
- module Assertions
- unless method_defined? :__assert_success_before_override_by_instiki
- alias :__assert_success_before_override_by_instiki :assert_success
- end
- def assert_success
- __assert_success_before_override_by_instiki
- if @response.body.kind_of?(Proc) then # it's a file download, not an HTML content
- else assert_nothing_raised(@response.body) { REXML::Document.new(@response.body) } end
- end
- end
- end
- end
-end
+ENV["RAILS_ENV"] = "test"
+
+# Expand the path to environment so that Ruby does not load it multiple times
+# File.expand_path can be removed if Ruby 1.9 is in use.
+require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
+require 'application'
+
+require 'test/unit'
+require 'active_record/fixtures'
+require 'action_controller/test_process'
+require 'action_web_service/test_invoke'
+require 'breakpoint'
+require 'wiki_content'
+
+# Uncomment these and hang on, because the tests will be FAST
+#Test::Unit::TestCase.pre_loaded_fixtures = false
+#Test::Unit::TestCase.use_transactional_fixtures = true
+
+Test::Unit::TestCase.use_instantiated_fixtures = false
+Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
+
+class Test::Unit::TestCase
+ def create_fixtures(*table_names)
+ Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures", table_names)
+ end
+
+ # Add more helper methods to be used by all tests here...
+ def set_web_property(property, value)
+ @web.update_attribute(property, value)
+ @page = Page.find(@page.id)
+ @wiki.webs[@web.name] = @web
+ end
+
+ def setup_wiki_with_30_pages
+ ActiveRecord::Base.silence do
+ (1..30).each do |i|
+ @wiki.write_page('wiki1', "page#{i}", "Test page #{i}\ncategory: test",
+ Time.local(1976, 10, i, 12, 00, 00), Author.new('Dema', '127.0.0.2'))
+ end
+ end
+ @web = Web.find(@web.id)
+ end
+
+ def use_blank_wiki
+ Revision.destroy_all
+ Page.destroy_all
+ Web.destroy_all
+ end
+end
+
+# This module is to be included in unit tests that involve matching chunks.
+# It provides a easy way to test whether a chunk matches a particular string
+# and any the values of any fields that should be set after a match.
+class ContentStub < String
+ include ChunkManager
+ def initialize(str)
+ super
+ init_chunk_manager
+ end
+ def page_link(*); end
+end
+
+module ChunkMatch
+
+ # Asserts a number of tests for the given type and text.
+ def match(chunk_type, test_text, expected_chunk_state)
+ if chunk_type.respond_to? :pattern
+ assert_match(chunk_type.pattern, test_text)
+ end
+
+ content = ContentStub.new(test_text)
+ chunk_type.apply_to(content)
+
+ # Test if requested parts are correct.
+ expected_chunk_state.each_pair do |a_method, expected_value|
+ assert content.chunks.last.kind_of?(chunk_type)
+ assert_respond_to(content.chunks.last, a_method)
+ assert_equal(expected_value, content.chunks.last.send(a_method.to_sym),
+ "Wrong #{a_method} value")
+ end
+ end
+
+ # Asserts that test_text doesn't match the chunk_type
+ def no_match(chunk_type, test_text)
+ if chunk_type.respond_to? :pattern
+ assert_no_match(chunk_type.pattern, test_text)
+ end
+ end
+end
+
+if defined? $validate_xml_in_assert_success and $validate_xml_in_assert_success == true
+ module Test
+ module Unit
+ module Assertions
+ unless method_defined? :__assert_success_before_override_by_instiki
+ alias :__assert_success_before_override_by_instiki :assert_success
+ end
+ def assert_success
+ __assert_success_before_override_by_instiki
+ if @response.body.kind_of?(Proc) then # it's a file download, not an HTML content
+ else assert_nothing_raised(@response.body) { REXML::Document.new(@response.body) } end
+ end
+ end
+ end
+ end
+end
diff --git a/test/unit/page_test.rb b/test/unit/page_test.rb
index 4f75d872..b3568271 100644
--- a/test/unit/page_test.rb
+++ b/test/unit/page_test.rb
@@ -1,88 +1,88 @@
-require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
-
-class PageTest < Test::Unit::TestCase
- fixtures :webs, :pages, :revisions, :system
-
- def setup
- @page = pages(:first_page)
- end
-
- def test_lock
- assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
-
- @page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
-
- assert @page.locked?(Time.local(2004, 4, 4, 16, 50))
- assert !@page.locked?(Time.local(2004, 4, 4, 17, 1))
-
- @page.unlock
-
- assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
- end
-
- def test_lock_duration
- @page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
-
- assert_equal 15, @page.lock_duration(Time.local(2004, 4, 4, 16, 45))
- end
-
- def test_plain_name
- assert_equal "First Page", @page.plain_name
- end
-
- def test_revise
- @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
- @page.reload
-
- assert_equal 2, @page.revisions.length, 'Should have two revisions'
- assert_equal 'MarianneSyhler', @page.current_revision.author.to_s, 'Mary should be the author now'
- assert_equal 'DavidHeinemeierHansson', @page.revisions.first.author.to_s, 'David was the first author'
- end
-
- def test_revise_continous_revision
- @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
- @page.reload
- assert_equal 2, @page.revisions.length
- assert_equal 'HisWay would be MyWay in kinda lame', @page.content
-
- # consecutive revision by the same author within 30 minutes doesn't create a new revision
- @page.revise('HisWay would be MyWay in kinda update', Time.local(2004, 4, 4, 16, 57), 'MarianneSyhler')
- @page.reload
- assert_equal 2, @page.revisions.length
- assert_equal 'HisWay would be MyWay in kinda update', @page.content
- assert_equal Time.local(2004, 4, 4, 16, 57), @page.revised_at
-
- # but consecutive revision by another author results in a new revision
- @page.revise('HisWay would be MyWay in the house', Time.local(2004, 4, 4, 16, 58), 'DavidHeinemeierHansson')
- @page.reload
- assert_equal 3, @page.revisions.length
- assert_equal 'HisWay would be MyWay in the house', @page.content
-
- # consecutive update after 30 minutes since the last one also creates a new revision,
- # even when it is by the same author
- @page.revise('HisWay would be MyWay in my way', Time.local(2004, 4, 4, 17, 30), 'DavidHeinemeierHansson')
- @page.reload
- assert_equal 4, @page.revisions.length
- end
-
- def test_revise_content_unchanged
- last_revision_before = @page.current_revision
- revisions_number_before = @page.revisions.size
-
- assert_raises(Instiki::ValidationError) {
- @page.revise(@page.current_revision.content, Time.now, 'AlexeyVerkhovsky')
- }
-
- assert_equal last_revision_before, @page.current_revision(true)
- assert_equal revisions_number_before, @page.revisions.size
- end
-
- def test_rollback
- @page.revise("spot two", Time.now, "David")
- @page.revise("spot three", Time.now + 2000, "David")
- assert_equal 3, @page.revisions(true).length, "Should have three revisions"
- @page.current_revision(true)
- @page.rollback(0, Time.now)
- assert_equal "HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\\\OverThere -- see SmartEngine in that SmartEngineGUI", @page.current_revision(true).content
- end
-end
+require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
+
+class PageTest < Test::Unit::TestCase
+ fixtures :webs, :pages, :revisions, :system
+
+ def setup
+ @page = pages(:first_page)
+ end
+
+ def test_lock
+ assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
+
+ @page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
+
+ assert @page.locked?(Time.local(2004, 4, 4, 16, 50))
+ assert !@page.locked?(Time.local(2004, 4, 4, 17, 1))
+
+ @page.unlock
+
+ assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
+ end
+
+ def test_lock_duration
+ @page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
+
+ assert_equal 15, @page.lock_duration(Time.local(2004, 4, 4, 16, 45))
+ end
+
+ def test_plain_name
+ assert_equal "First Page", @page.plain_name
+ end
+
+ def test_revise
+ @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
+ @page.reload
+
+ assert_equal 2, @page.revisions.length, 'Should have two revisions'
+ assert_equal 'MarianneSyhler', @page.current_revision.author.to_s, 'Mary should be the author now'
+ assert_equal 'DavidHeinemeierHansson', @page.revisions.first.author.to_s, 'David was the first author'
+ end
+
+ def test_revise_continous_revision
+ @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
+ @page.reload
+ assert_equal 2, @page.revisions.length
+ assert_equal 'HisWay would be MyWay in kinda lame', @page.content
+
+ # consecutive revision by the same author within 30 minutes doesn't create a new revision
+ @page.revise('HisWay would be MyWay in kinda update', Time.local(2004, 4, 4, 16, 57), 'MarianneSyhler')
+ @page.reload
+ assert_equal 2, @page.revisions.length
+ assert_equal 'HisWay would be MyWay in kinda update', @page.content
+ assert_equal Time.local(2004, 4, 4, 16, 57), @page.revised_at
+
+ # but consecutive revision by another author results in a new revision
+ @page.revise('HisWay would be MyWay in the house', Time.local(2004, 4, 4, 16, 58), 'DavidHeinemeierHansson')
+ @page.reload
+ assert_equal 3, @page.revisions.length
+ assert_equal 'HisWay would be MyWay in the house', @page.content
+
+ # consecutive update after 30 minutes since the last one also creates a new revision,
+ # even when it is by the same author
+ @page.revise('HisWay would be MyWay in my way', Time.local(2004, 4, 4, 17, 30), 'DavidHeinemeierHansson')
+ @page.reload
+ assert_equal 4, @page.revisions.length
+ end
+
+ def test_revise_content_unchanged
+ last_revision_before = @page.current_revision
+ revisions_number_before = @page.revisions.size
+
+ assert_raises(Instiki::ValidationError) {
+ @page.revise(@page.current_revision.content, Time.now, 'AlexeyVerkhovsky')
+ }
+
+ assert_equal last_revision_before, @page.current_revision(true)
+ assert_equal revisions_number_before, @page.revisions.size
+ end
+
+ def test_rollback
+ @page.revise("spot two", Time.now, "David")
+ @page.revise("spot three", Time.now + 2000, "David")
+ assert_equal 3, @page.revisions(true).length, "Should have three revisions"
+ @page.current_revision(true)
+ @page.rollback(0, Time.now)
+ assert_equal "HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\\\OverThere -- see SmartEngine in that SmartEngineGUI", @page.current_revision(true).content
+ end
+end
diff --git a/test/unit/revision_test.rb b/test/unit/revision_test.rb
index d563ccde..f22bfd5d 100644
--- a/test/unit/revision_test.rb
+++ b/test/unit/revision_test.rb
@@ -1,317 +1,317 @@
-require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
-
-class RevisionTest < Test::Unit::TestCase
- fixtures :webs, :pages, :revisions, :system
-
- def setup
- @wiki = Wiki.new
- @web = webs(:test_wiki)
- @page = pages(:home_page)
- @revision = revisions(:home_page_second_revision)
- end
-
- def test_wiki_words
- assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ), @revision.wiki_words.sort
-
- @wiki.write_page('wiki1', 'NoWikiWord', 'hey you!', Time.now, 'Me')
- assert_equal [], @wiki.read_page('wiki1', 'NoWikiWord').wiki_words
- end
-
- def test_existing_pages
- assert_equal %w( MyWay SmartEngine ThatWay ), @revision.existing_pages.sort
- end
-
- def test_unexisting_pages
- assert_equal %w( HisWay SmartEngineGUI ), @revision.unexisting_pages.sort
- end
-
- def test_content_with_wiki_links
- assert_equal '
His Way? ' +
- 'would be My Way in kinda ' +
- 'That Way in ' +
- 'His Way? ' +
- 'though My Way OverThere—see ' +
- 'Smart Engine in that ' +
- 'Smart Engine GUI' +
- '?
',
- '("What is a wiki?":http://wiki.org/wiki.cgi?WhatIsWiki)')
- end
-
- def test_content_with_image_link
- assert_markup_parsed_as(
- '
This is a Textile image link.
',
- 'This !http://hobix.com/sample.jpg! is a Textile image link.')
- end
-
- def test_content_with_inlined_img_tag
- assert_markup_parsed_as(
- '
This is an inline image link.
',
- 'This is an inline image link.')
-
- assert_markup_parsed_as(
- '
This is an inline image link.
',
- 'This is an inline image link.')
- end
-
- def test_nowiki_tag
- assert_markup_parsed_as(
- '
Do not mark up [[this text]] or http://www.thislink.com.
',
- 'Do not mark up [[this text]] ' +
- 'or http://www.thislink.com.')
- end
-
- def test_multiline_nowiki_tag
- assert_markup_parsed_as(
- "
Do not mark \n up [[this text]] \nand http://this.url.com but markup " +
- 'this?
',
- "Do not mark \n up [[this text]] \n" +
- "and http://this.url.com but markup [[this]]")
- end
-
- def test_content_with_bracketted_wiki_word
- set_web_property :brackets_only, true
- assert_markup_parsed_as(
- '
This is a WikiWord and a tricky name ' +
- 'Sperberg-McQueen?.
',
- 'This is a WikiWord and a tricky name [[Sperberg-McQueen]].')
- end
-
- def test_content_for_export
- assert_equal '
His Way would be ' +
- 'My Way in kinda ' +
- 'That Way in ' +
- 'His Way though ' +
- 'My Way OverThere—see ' +
- 'Smart Engine in that ' +
- 'Smart Engine GUI
',
- '[[With:Colon]]')
- end
-
- # TODO Remove the leading underscores from this test when upgrading to RedCloth 3.0.1;
- # also add a test for the "Unhappy Face" problem (another interesting RedCloth bug)
- def test_list_with_tildas
- list_with_tildas = <<-EOL
- * "a":~b
- * c~ d
- EOL
-
- assert_markup_parsed_as(
- "
His Way? ' +
+ 'would be My Way in kinda ' +
+ 'That Way in ' +
+ 'His Way? ' +
+ 'though My Way OverThere—see ' +
+ 'Smart Engine in that ' +
+ 'Smart Engine GUI' +
+ '?
',
+ '("What is a wiki?":http://wiki.org/wiki.cgi?WhatIsWiki)')
+ end
+
+ def test_content_with_image_link
+ assert_markup_parsed_as(
+ '
This is a Textile image link.
',
+ 'This !http://hobix.com/sample.jpg! is a Textile image link.')
+ end
+
+ def test_content_with_inlined_img_tag
+ assert_markup_parsed_as(
+ '
This is an inline image link.
',
+ 'This is an inline image link.')
+
+ assert_markup_parsed_as(
+ '
This is an inline image link.
',
+ 'This is an inline image link.')
+ end
+
+ def test_nowiki_tag
+ assert_markup_parsed_as(
+ '
Do not mark up [[this text]] or http://www.thislink.com.
',
+ 'Do not mark up [[this text]] ' +
+ 'or http://www.thislink.com.')
+ end
+
+ def test_multiline_nowiki_tag
+ assert_markup_parsed_as(
+ "
Do not mark \n up [[this text]] \nand http://this.url.com but markup " +
+ 'this?
',
+ "Do not mark \n up [[this text]] \n" +
+ "and http://this.url.com but markup [[this]]")
+ end
+
+ def test_content_with_bracketted_wiki_word
+ set_web_property :brackets_only, true
+ assert_markup_parsed_as(
+ '
This is a WikiWord and a tricky name ' +
+ 'Sperberg-McQueen?.
',
+ 'This is a WikiWord and a tricky name [[Sperberg-McQueen]].')
+ end
+
+ def test_content_for_export
+ assert_equal '
His Way would be ' +
+ 'My Way in kinda ' +
+ 'That Way in ' +
+ 'His Way though ' +
+ 'My Way OverThere—see ' +
+ 'Smart Engine in that ' +
+ 'Smart Engine GUI
',
+ '[[With:Colon]]')
+ end
+
+ # TODO Remove the leading underscores from this test when upgrading to RedCloth 3.0.1;
+ # also add a test for the "Unhappy Face" problem (another interesting RedCloth bug)
+ def test_list_with_tildas
+ list_with_tildas = <<-EOL
+ * "a":~b
+ * c~ d
+ EOL
+
+ assert_markup_parsed_as(
+ "
diff --git a/app/views/wiki/rss_feed.rhtml b/app/views/wiki/rss_feed.rhtml
index f6e63352..47815c49 100644
--- a/app/views/wiki/rss_feed.rhtml
+++ b/app/views/wiki/rss_feed.rhtml
@@ -7,10 +7,10 @@
en-us40
<% for page in @pages_by_revision %>
-
+ <%= h page.plain_name %>
<% unless @hide_description %>
- <%= h page.display_content %>
+ <%= h rendered_content(page) %>
<% end %>
<%= page.revised_at.getgm.strftime "%a, %d %b %Y %H:%M:%S Z" %><%= url_for :only_path => false, :web => @web_name, :action => @link_action, :id => page.name %>
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 3f0868e6..d214c666 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -1,4 +1,14 @@
-Dependencies.mechanism = :require
+# In the development environment your application's code is reloaded on
+# every request. This slows down response time but is perfect for development
+# since you don't have to restart the webserver when you make code changes.
+
+# Log error messages when you accidentally call methods on nil.
+require 'active_support/whiny_nil'
+
+# Reload code; show full error reports; disable caching.
+Dependencies.mechanism = :load
ActionController::Base.consider_all_requests_local = true
-ActionController::Base.perform_caching = false
+ActionController::Base.perform_caching = false
+
+# The breakpoint server port that script/breakpointer connects to.
BREAKPOINT_SERVER_PORT = 42531
diff --git a/lib/page_renderer.rb b/lib/page_renderer.rb
new file mode 100644
index 00000000..c9887404
--- /dev/null
+++ b/lib/page_renderer.rb
@@ -0,0 +1,106 @@
+# Temporary class containing all rendering stuff from a Revision
+# I want to shift all rendering loguc to the controller eventually
+
+class PageRenderer
+
+ def initialize(revision)
+ @revision = revision
+ end
+
+ # Returns an array of all the WikiIncludes present in the content of this revision.
+ def wiki_includes
+ unless @wiki_includes_cache
+ chunks = display_content.find_chunks(Include)
+ @wiki_includes_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
+ end
+ @wiki_includes_cache
+ end
+
+ # Returns an array of all the WikiReferences present in the content of this revision.
+ def wiki_references
+ unless @wiki_references_cache
+ chunks = display_content.find_chunks(WikiChunk::WikiReference)
+ @wiki_references_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
+ end
+ @wiki_references_cache
+ end
+
+ # Returns an array of all the WikiWords present in the content of this revision.
+ def wiki_words
+ unless @wiki_words_cache
+ wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
+ @wiki_words_cache = wiki_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
+ end
+ @wiki_words_cache
+ end
+
+ # Returns an array of all the WikiWords present in the content of this revision.
+ # that already exists as a page in the web.
+ def existing_pages
+ wiki_words.select { |wiki_word| @revision.page.web.page(wiki_word) }
+ end
+
+ # Returns an array of all the WikiWords present in the content of this revision
+ # that *doesn't* already exists as a page in the web.
+ def unexisting_pages
+ wiki_words - existing_pages
+ end
+
+ # Explicit check for new type of display cache with chunks_by_type method.
+ # Ensures new version works with older snapshots.
+ def display_content
+ unless @display_cache && @display_cache.respond_to?(:chunks_by_type)
+ @display_cache = WikiContent.new(@revision)
+ @display_cache.render!
+ end
+ @display_cache
+ end
+
+ # TODO this probably doesn't belong in revision (because it has to call back the page)
+ def display_diff
+ previous_revision = @revision.page.previous_revision(@revision)
+ if previous_revision
+ HTMLDiff.diff(PageRenderer.new(previous_revision).display_content, display_content)
+ else
+ display_content
+ end
+ end
+
+ def clear_display_cache
+ @wiki_words_cache = @published_cache = @display_cache = @wiki_includes_cache =
+ @wiki_references_cache = nil
+ end
+
+ def display_published
+ unless @published_cache && @published_cache.respond_to?(:chunks_by_type)
+ @published_cache = WikiContent.new(@revision, {:mode => :publish})
+ @published_cache.render!
+ end
+ @published_cache
+ end
+
+ def display_content_for_export
+ WikiContent.new(@revision, {:mode => :export} ).render!
+ end
+
+ def force_rendering
+ begin
+ display_content.render!
+ rescue => e
+ logger.error "Failed rendering page #{@name}"
+ logger.error e
+ message = e.message
+ # substitute content with an error message
+ @revision.content = <<-EOL
+
Markup engine has failed to render this page, raising the following error:
+
#{message}
+
#{self.content}
+ EOL
+ clear_display_cache
+ raise e
+ end
+ end
+
+ protected
+
+end
\ No newline at end of file
diff --git a/test/functional/file_controller_test.rb b/test/functional/file_controller_test.rb
index a7023aff..01586b09 100755
--- a/test/functional/file_controller_test.rb
+++ b/test/functional/file_controller_test.rb
@@ -96,8 +96,8 @@ class FileControllerTest < Test::Unit::TestCase
@wiki.revise_page('wiki1', 'HomePage', '[[instiki-e2e.txt:file]]', Time.now, 'AnonymousBrave')
assert_equal "
",
- @home.display_content
-
+ PageRenderer.new(@home.revisions.last).display_content
+
# rails-e2e.gif is unknown to the system, so pic action goes to the file [upload] form
r = process 'file', 'web' => 'wiki1', 'id' => 'instiki-e2e.txt'
assert_success
@@ -114,7 +114,7 @@ class FileControllerTest < Test::Unit::TestCase
@home = Page.find(@home.id)
assert_equal "
His Way? ' +
- 'would be My Way in kinda ' +
- 'That Way in ' +
- 'His Way? ' +
- 'though My Way OverThere—see ' +
- 'Smart Engine in that ' +
- 'Smart Engine GUI' +
- '?
',
- '("What is a wiki?":http://wiki.org/wiki.cgi?WhatIsWiki)')
- end
-
- def test_content_with_image_link
- assert_markup_parsed_as(
- '
This is a Textile image link.
',
- 'This !http://hobix.com/sample.jpg! is a Textile image link.')
- end
-
- def test_content_with_inlined_img_tag
- assert_markup_parsed_as(
- '
This is an inline image link.
',
- 'This is an inline image link.')
-
- assert_markup_parsed_as(
- '
This is an inline image link.
',
- 'This is an inline image link.')
- end
-
- def test_nowiki_tag
- assert_markup_parsed_as(
- '
Do not mark up [[this text]] or http://www.thislink.com.
',
- 'Do not mark up [[this text]] ' +
- 'or http://www.thislink.com.')
- end
-
- def test_multiline_nowiki_tag
- assert_markup_parsed_as(
- "
Do not mark \n up [[this text]] \nand http://this.url.com but markup " +
- 'this?
',
- "Do not mark \n up [[this text]] \n" +
- "and http://this.url.com but markup [[this]]")
- end
-
- def test_content_with_bracketted_wiki_word
- set_web_property :brackets_only, true
- assert_markup_parsed_as(
- '
This is a WikiWord and a tricky name ' +
- 'Sperberg-McQueen?.
',
- 'This is a WikiWord and a tricky name [[Sperberg-McQueen]].')
- end
-
- def test_content_for_export
- assert_equal '
His Way would be ' +
- 'My Way in kinda ' +
- 'That Way in ' +
- 'His Way though ' +
- 'My Way OverThere—see ' +
- 'Smart Engine in that ' +
- 'Smart Engine GUI
',
- '[[With:Colon]]')
- end
-
- # TODO Remove the leading underscores from this test when upgrading to RedCloth 3.0.1;
- # also add a test for the "Unhappy Face" problem (another interesting RedCloth bug)
- def test_list_with_tildas
- list_with_tildas = <<-EOL
- * "a":~b
- * c~ d
- EOL
-
- assert_markup_parsed_as(
- "
',
+ rendered_content(@web.page("SecondPage")))
+ end
+
+ def test_make_link
+ add_sample_pages
+
+ existing_page_wiki_url =
+ 'Ever Been In Love'
+ existing_page_published_url =
+ 'Ever Been In Love'
+ existing_page_static_url =
+ 'Ever Been In Love'
+ new_page_wiki_url =
+ 'Unknown Word?'
+ new_page_published_url = new_page_static_url = 'Unknown Word'
+
+ # no options
+ assert_equal existing_page_wiki_url, @web.make_link('EverBeenInLove')
+
+ # :mode => :export
+ assert_equal existing_page_static_url, @web.make_link('EverBeenInLove', nil, :mode => :export)
+
+ # :mode => :publish
+ assert_equal existing_page_published_url,
+ @web.make_link('EverBeenInLove', nil, :mode => :publish)
+
+ # new page, no options
+ assert_equal new_page_wiki_url, @web.make_link('UnknownWord')
+
+ # new page, :mode => :export
+ assert_equal new_page_static_url, @web.make_link('UnknownWord', nil, :mode => :export)
+
+ # new page, :mode => :publish
+ assert_equal new_page_published_url, @web.make_link('UnknownWord', nil, :mode => :publish)
+
+ # Escaping special characters in the name
+ assert_equal(
+ 'Smith & Wesson?',
+ @web.make_link('Smith & Wesson'))
+
+ # optionally using text as the link text
+ assert_equal(
+ existing_page_published_url.sub(/>Ever Been In Love, ">Haven't you ever been in love?<"),
+ @web.make_link('EverBeenInLove', "Haven't you ever been in love?", :mode => :publish))
+
+ end
+
+ def test_wiki_words
+ assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ),
+ PageRenderer.new(@revision).wiki_words.sort
+
+ @wiki.write_page('wiki1', 'NoWikiWord', 'hey you!', Time.now, 'Me')
+ assert_equal [], PageRenderer.new(@wiki.read_page('wiki1', 'NoWikiWord').revisions.last).wiki_words
+ end
+
+ def test_existing_pages
+ assert_equal %w( MyWay SmartEngine ThatWay ), PageRenderer.new(@revision).existing_pages.sort
+ end
+
+ def test_unexisting_pages
+ assert_equal %w( HisWay SmartEngineGUI ), PageRenderer.new(@revision).unexisting_pages.sort
+ end
+
+ def test_content_with_wiki_links
+ assert_equal '
His Way? ' +
+ 'would be My Way in kinda ' +
+ 'That Way in ' +
+ 'His Way? ' +
+ 'though My Way OverThere—see ' +
+ 'Smart Engine in that ' +
+ 'Smart Engine GUI' +
+ '?
',
+ '("What is a wiki?":http://wiki.org/wiki.cgi?WhatIsWiki)')
+ end
+
+ def test_content_with_image_link
+ assert_markup_parsed_as(
+ '
This is a Textile image link.
',
+ 'This !http://hobix.com/sample.jpg! is a Textile image link.')
+ end
+
+ def test_content_with_inlined_img_tag
+ assert_markup_parsed_as(
+ '
This is an inline image link.
',
+ 'This is an inline image link.')
+
+ assert_markup_parsed_as(
+ '
This is an inline image link.
',
+ 'This is an inline image link.')
+ end
+
+ def test_nowiki_tag
+ assert_markup_parsed_as(
+ '
Do not mark up [[this text]] or http://www.thislink.com.
',
+ 'Do not mark up [[this text]] ' +
+ 'or http://www.thislink.com.')
+ end
+
+ def test_multiline_nowiki_tag
+ assert_markup_parsed_as(
+ "
Do not mark \n up [[this text]] \nand http://this.url.com but markup " +
+ 'this?
',
+ "Do not mark \n up [[this text]] \n" +
+ "and http://this.url.com but markup [[this]]")
+ end
+
+ def test_content_with_bracketted_wiki_word
+ set_web_property :brackets_only, true
+ assert_markup_parsed_as(
+ '
This is a WikiWord and a tricky name ' +
+ 'Sperberg-McQueen?.
',
+ 'This is a WikiWord and a tricky name [[Sperberg-McQueen]].')
+ end
+
+ def test_content_for_export
+ assert_equal '
His Way would be ' +
+ 'My Way in kinda ' +
+ 'That Way in ' +
+ 'His Way though ' +
+ 'My Way OverThere—see ' +
+ 'Smart Engine in that ' +
+ 'Smart Engine GUI
',
+ '[[With:Colon]]')
+ end
+
+ # TODO Remove the leading underscores from this test when upgrading to RedCloth 3.0.1;
+ # also add a test for the "Unhappy Face" problem (another interesting RedCloth bug)
+ def test_list_with_tildas
+ list_with_tildas = <<-EOL
+ * "a":~b
+ * c~ d
+ EOL
+
+ assert_markup_parsed_as(
+ "
",
- PageRenderer.new(@home.revisions.last).display_content
+ test_renderer(@home.revisions.last).display_content
# rails-e2e.gif is unknown to the system, so pic action goes to the file [upload] form
r = process 'file', 'web' => 'wiki1', 'id' => 'instiki-e2e.txt'
@@ -114,7 +115,7 @@ class FileControllerTest < Test::Unit::TestCase
@home = Page.find(@home.id)
assert_equal "
His Way would be ' +
- 'My Way in kinda ' +
- 'That Way in ' +
- 'His Way though ' +
- 'My Way OverThere—see ' +
- 'Smart Engine in that ' +
- 'Smart Engine GUI
',
- PageRenderer.new(@revision).display_content_for_export
+ 'My Way in kinda ' +
+ 'That Way in ' +
+ 'His Way though ' +
+ 'My Way OverThere—see ' +
+ 'Smart Engine in that ' +
+ 'Smart Engine GUI',
+ test_renderer(@revision).display_content_for_export
end
def test_double_replacing
@revision.content = "VersionHistory\r\n\r\ncry VersionHistory"
assert_equal '
",
- PageRenderer.new(@revision).display_content
+ "?",
+ test_renderer(@revision).display_content
end
def test_revisions_diff
@@ -311,7 +311,7 @@ class PageRendererTest < Test::Unit::TestCase
assert_equal "
What a blue red " +
"and lovely morningmorning " +
- "today
", PageRenderer.new(@page.revisions.last).display_diff
+ "today", test_renderer(@page.revisions.last).display_diff
end
def test_link_to_file
@@ -373,18 +373,18 @@ class PageRendererTest < Test::Unit::TestCase
def add_sample_pages
@in_love = @web.add_page('EverBeenInLove', 'Who am I me',
- Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
+ Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson', test_renderer)
@hated = @web.add_page('EverBeenHated', 'I am me EverBeenHated',
- Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson')
+ Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson', test_renderer)
end
def assert_markup_parsed_as(expected_output, input)
revision = Revision.new(:page => @page, :content => input, :author => Author.new('AnAuthor'))
- assert_equal expected_output, PageRenderer.new(revision).display_content, 'Rendering output not as expected'
+ assert_equal expected_output, test_renderer(revision).display_content, 'Rendering output not as expected'
end
def rendered_content(page)
- PageRenderer.new(page.revisions.last).display_content
+ test_renderer(page.revisions.last).display_content
end
end
\ No newline at end of file
diff --git a/test/unit/page_test.rb b/test/unit/page_test.rb
index b3568271..8b63f67a 100644
--- a/test/unit/page_test.rb
+++ b/test/unit/page_test.rb
@@ -31,36 +31,43 @@ class PageTest < Test::Unit::TestCase
end
def test_revise
- @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
+ @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55),
+ 'MarianneSyhler', test_renderer)
@page.reload
assert_equal 2, @page.revisions.length, 'Should have two revisions'
- assert_equal 'MarianneSyhler', @page.current_revision.author.to_s, 'Mary should be the author now'
- assert_equal 'DavidHeinemeierHansson', @page.revisions.first.author.to_s, 'David was the first author'
+ assert_equal 'MarianneSyhler', @page.current_revision.author.to_s,
+ 'Mary should be the author now'
+ assert_equal 'DavidHeinemeierHansson', @page.revisions.first.author.to_s,
+ 'David was the first author'
end
def test_revise_continous_revision
- @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
+ @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55),
+ 'MarianneSyhler', test_renderer)
@page.reload
assert_equal 2, @page.revisions.length
assert_equal 'HisWay would be MyWay in kinda lame', @page.content
# consecutive revision by the same author within 30 minutes doesn't create a new revision
- @page.revise('HisWay would be MyWay in kinda update', Time.local(2004, 4, 4, 16, 57), 'MarianneSyhler')
+ @page.revise('HisWay would be MyWay in kinda update', Time.local(2004, 4, 4, 16, 57),
+ 'MarianneSyhler', test_renderer)
@page.reload
assert_equal 2, @page.revisions.length
assert_equal 'HisWay would be MyWay in kinda update', @page.content
assert_equal Time.local(2004, 4, 4, 16, 57), @page.revised_at
# but consecutive revision by another author results in a new revision
- @page.revise('HisWay would be MyWay in the house', Time.local(2004, 4, 4, 16, 58), 'DavidHeinemeierHansson')
+ @page.revise('HisWay would be MyWay in the house', Time.local(2004, 4, 4, 16, 58),
+ 'DavidHeinemeierHansson', test_renderer)
@page.reload
assert_equal 3, @page.revisions.length
assert_equal 'HisWay would be MyWay in the house', @page.content
# consecutive update after 30 minutes since the last one also creates a new revision,
# even when it is by the same author
- @page.revise('HisWay would be MyWay in my way', Time.local(2004, 4, 4, 17, 30), 'DavidHeinemeierHansson')
+ @page.revise('HisWay would be MyWay in my way', Time.local(2004, 4, 4, 17, 30),
+ 'DavidHeinemeierHansson', test_renderer)
@page.reload
assert_equal 4, @page.revisions.length
end
@@ -70,7 +77,7 @@ class PageTest < Test::Unit::TestCase
revisions_number_before = @page.revisions.size
assert_raises(Instiki::ValidationError) {
- @page.revise(@page.current_revision.content, Time.now, 'AlexeyVerkhovsky')
+ @page.revise(@page.current_revision.content, Time.now, 'AlexeyVerkhovsky', test_renderer)
}
assert_equal last_revision_before, @page.current_revision(true)
@@ -78,11 +85,11 @@ class PageTest < Test::Unit::TestCase
end
def test_rollback
- @page.revise("spot two", Time.now, "David")
- @page.revise("spot three", Time.now + 2000, "David")
+ @page.revise("spot two", Time.now, "David", test_renderer)
+ @page.revise("spot three", Time.now + 2000, "David", test_renderer)
assert_equal 3, @page.revisions(true).length, "Should have three revisions"
@page.current_revision(true)
- @page.rollback(0, Time.now)
+ @page.rollback(0, Time.now, '127.0.0.1', test_renderer)
assert_equal "HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\\\OverThere -- see SmartEngine in that SmartEngineGUI", @page.current_revision(true).content
end
end
diff --git a/test/unit/web_test.rb b/test/unit/web_test.rb
index bfa6edd7..ea08523a 100644
--- a/test/unit/web_test.rb
+++ b/test/unit/web_test.rb
@@ -61,9 +61,9 @@ class WebTest < Test::Unit::TestCase
def test_new_page_linked_from_mother_page
# this was a bug in revision 204
home = @web.add_page('HomePage', 'This page refers to AnotherPage',
- Time.local(2004, 4, 4, 16, 50), 'Alexey Verkhovsky')
+ Time.local(2004, 4, 4, 16, 50), 'Alexey Verkhovsky', test_renderer)
@web.add_page('AnotherPage', 'This is \AnotherPage',
- Time.local(2004, 4, 4, 16, 51), 'Alexey Verkhovsky')
+ Time.local(2004, 4, 4, 16, 51), 'Alexey Verkhovsky', test_renderer)
@web.pages(true)
assert_equal [home], @web.select.pages_that_link_to('AnotherPage')
@@ -73,13 +73,13 @@ class WebTest < Test::Unit::TestCase
add_sample_pages
home = @web.add_page('HomePage',
'This is a home page, it should not be an orphan',
- Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
+ Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', test_renderer)
author = @web.add_page('AlexeyVerkhovsky',
'This is an author page, it should not be an orphan',
- Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
+ Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', test_renderer)
self_linked = @web.add_page('SelfLinked',
'I am me SelfLinked and link to EverBeenInLove',
- Time.local(2004, 4, 4, 16, 50), 'AnonymousCoward')
+ Time.local(2004, 4, 4, 16, 50), 'AnonymousCoward', test_renderer)
# page that links to itself, and nobody else links to it must be an orphan
assert_equal ['EverBeenHated', 'SelfLinked'],
@@ -90,8 +90,8 @@ class WebTest < Test::Unit::TestCase
def add_sample_pages
@in_love = @web.add_page('EverBeenInLove', 'Who am I me',
- Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
+ Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson', test_renderer)
@hated = @web.add_page('EverBeenHated', 'I am me EverBeenHated',
- Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson')
+ Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson', test_renderer)
end
end
From 70fa15e3f38aa7efbe517c061b6292a26f7ef69a Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Sat, 10 Sep 2005 11:07:40 +0000
Subject: [PATCH 45/84] Continue extracting URL generation logic from model
classes
---
app/controllers/application.rb | 12 ++-
app/helpers/application_helper.rb | 7 +-
app/models/page.rb | 13 ---
app/models/web.rb | 22 -----
app/views/wiki/page.rhtml | 2 +-
app/views/wiki/print.rhtml | 2 +-
lib/page_renderer.rb | 21 +++--
lib/url_generator.rb | 128 ++++++++++++++++++++++--------
lib/wiki_content.rb | 5 +-
test/test_helper.rb | 60 ++++++++++++++
test/unit/page_renderer_test.rb | 44 ----------
test/watir/e2e.rb | 2 +-
12 files changed, 191 insertions(+), 127 deletions(-)
diff --git a/app/controllers/application.rb b/app/controllers/application.rb
index a126f845..2208066a 100644
--- a/app/controllers/application.rb
+++ b/app/controllers/application.rb
@@ -2,8 +2,8 @@
# Likewise will all the methods added be available for all controllers.
class ApplicationController < ActionController::Base
- before_filter :set_utf8_http_header, :connect_to_model
- after_filter :remember_location
+ before_filter :set_utf8_http_header, :connect_to_model, :setup_url_generator
+ after_filter :remember_location, :teardown_url_generator
# For injecting a different wiki model implementation. Intended for use in tests
def self.wiki=(the_wiki)
@@ -146,6 +146,14 @@ class ApplicationController < ActionController::Base
@response.headers['Content-Type'] = 'text/html; charset=UTF-8'
end
+ def setup_url_generator
+ PageRenderer.setup_url_generator(UrlGenerator.new(self))
+ end
+
+ def teardown_url_generator
+ PageRenderer.teardown_url_generator
+ end
+
def wiki
self.class.wiki
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 491fb410..f72c572d 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -44,7 +44,12 @@ module ApplicationHelper
# Creates a hyperlink to a Wiki page, or to a "new page" form if the page doesn't exist yet
def link_to_page(page_name, web = @web, text = nil, options = {})
raise 'Web not defined' if web.nil?
- web.make_link(page_name, text, options.merge(:base_url => "#{base_url}/#{web.address}"))
+ UrlGenerator.new(@controller).make_link(page_name, web, text,
+ options.merge(:base_url => "#{base_url}/#{web.address}"))
+ end
+
+ def author_link(page, options = {})
+ UrlGenerator.new(@controller).make_link(page.author.name, page.web, nil, options)
end
def base_url
diff --git a/app/models/page.rb b/app/models/page.rb
index 1179e9f8..7d0e8695 100644
--- a/app/models/page.rb
+++ b/app/models/page.rb
@@ -79,19 +79,6 @@ class Page < ActiveRecord::Base
web.brackets_only? ? name : WikiWords.separate(name)
end
- # used to build chunk ids.
- #def id
- # @id ||= name.unpack('H*').first
- #end
-
- def link(options = {})
- web.make_link(name, nil, options)
- end
-
- def author_link(options = {})
- web.make_link(author, nil, options)
- end
-
LOCKING_PERIOD = 30.minutes
def lock(time, locked_by)
diff --git a/app/models/web.rb b/app/models/web.rb
index f3fb5534..e3b2f7d0 100644
--- a/app/models/web.rb
+++ b/app/models/web.rb
@@ -44,28 +44,6 @@ class Web < ActiveRecord::Base
read_attribute('markup').to_sym
end
- # Create a link for the given page name and link text based
- # on the render mode in options and whether the page exists
- # in the this web.
- # The links a relative, and will work only if displayed on another WikiPage.
- # It should not be used in menus, templates and such - instead, use link_to_page helper
- def make_link(name, text = nil, options = {})
- text = CGI.escapeHTML(text || WikiWords.separate(name))
- mode = options[:mode] || :show
- base_url = options[:base_url] || '..'
- link_type = options[:link_type] || :show
- case link_type.to_sym
- when :show
- UrlGenerator.new.make_page_link(mode, name, text, base_url, has_page?(name))
- when :file
- UrlGenerator.new.make_file_link(mode, name, text, base_url, has_file?(name))
- when :pic
- UrlGenerator.new.make_pic_link(mode, name, text, base_url, has_file?(name))
- else
- raise "Unknown link type: #{link_type}"
- end
- end
-
def remove_pages(pages_to_be_removed)
pages_to_be_removed.each { |p| p.destroy }
end
diff --git a/app/views/wiki/page.rhtml b/app/views/wiki/page.rhtml
index 57c06927..432f688b 100644
--- a/app/views/wiki/page.rhtml
+++ b/app/views/wiki/page.rhtml
@@ -23,7 +23,7 @@
<%= @page.revisions? ? "Revised" : "Created" %> on <%= format_date(@page.revised_at) %>
- by <%= @page.author_link %>
+ by <%= author_link(@page) %>
<%= "(#{@page.author.ip})" if @page.author.respond_to?(:ip) %>
<% if @web.count_pages? %>
<% total_chars = @page.content.length %>
diff --git a/app/views/wiki/print.rhtml b/app/views/wiki/print.rhtml
index 3bc191a8..177e92f1 100644
--- a/app/views/wiki/print.rhtml
+++ b/app/views/wiki/print.rhtml
@@ -10,5 +10,5 @@
diff --git a/lib/page_renderer.rb b/lib/page_renderer.rb
index e516b2cf..db10730a 100644
--- a/lib/page_renderer.rb
+++ b/lib/page_renderer.rb
@@ -4,8 +4,17 @@ require 'diff'
class PageRenderer
+ def self.setup_url_generator(url_generator)
+ @@url_generator = url_generator
+ end
+
+ def self.teardown_url_generator
+ @@url_generator = nil
+ end
+
attr_accessor :revision
+
def initialize(revision = nil)
@revision = revision
end
@@ -53,7 +62,7 @@ class PageRenderer
# Ensures new version works with older snapshots.
def display_content
unless @display_cache && @display_cache.respond_to?(:chunks_by_type)
- @display_cache = WikiContent.new(@revision)
+ @display_cache = WikiContent.new(@revision, @@url_generator)
@display_cache.render!
end
@display_cache
@@ -76,28 +85,28 @@ class PageRenderer
def display_published
unless @published_cache && @published_cache.respond_to?(:chunks_by_type)
- @published_cache = WikiContent.new(@revision, {:mode => :publish})
+ @published_cache = WikiContent.new(@revision, @@url_generator, {:mode => :publish})
@published_cache.render!
end
@published_cache
end
def display_content_for_export
- WikiContent.new(@revision, {:mode => :export} ).render!
+ WikiContent.new(@revision, @@url_generator, {:mode => :export} ).render!
end
def force_rendering
begin
display_content.render!
rescue => e
- logger.error "Failed rendering page #{@name}"
- logger.error e
+ ActionController::Base.logger.error "Failed rendering page #{@name}"
+ ActionController::Base.logger.error e
message = e.message
# substitute content with an error message
@revision.content = <<-EOL
Markup engine has failed to render this page, raising the following error:
#{message}
-
#{self.content}
+
#{@revision.content}
EOL
clear_display_cache
raise e
diff --git a/lib/url_generator.rb b/lib/url_generator.rb
index 4fd1ff93..fcc08312 100644
--- a/lib/url_generator.rb
+++ b/lib/url_generator.rb
@@ -1,61 +1,121 @@
-class UrlGenerator
+class AbstractUrlGenerator
- def initialize(controller = nil)
- @controller = controller or ControllerStub.new
+ def initialize(controller)
+ raise 'Controller cannot be nil' if controller.nil?
+ @controller = controller
end
- def make_file_link(mode, name, text, base_url, known_file)
- link = CGI.escape(name)
+ # Create a link for the given page (or file) name and link text based
+ # on the render mode in options and whether the page (file) exists
+ # in the web.
+ def make_link(name, web, text = nil, options = {})
+ text = CGI.escapeHTML(text || WikiWords.separate(name))
+ mode = (options[:mode] || :show).to_sym
+ link_type = (options[:link_type] || :show).to_sym
+
+ if (link_type == :show)
+ known_page = web.has_page?(name)
+ else
+ known_page = web.has_file?(name)
+ end
+
+ case link_type
+ when :show
+ page_link(mode, name, text, web.address, known_page)
+ when :file
+ file_link(mode, name, text, web.address, known_page)
+ when :pic
+ pic_link(mode, name, text, web.address, known_page)
+ else
+ raise "Unknown link type: #{link_type}"
+ end
+ end
+
+end
+
+class UrlGenerator < AbstractUrlGenerator
+
+ private
+
+ def file_link(mode, name, text, web_address, known_file)
case mode
when :export
- if known_file then "#{text}"
- else "#{text}" end
- when :publish
- if known_file then "#{text}"
- else "#{text}" end
- else
if known_file
- "#{text}"
+ %{#{text}}
else
- "#{text}?"
+ %{#{text}}
+ end
+ when :publish
+ if known_file
+ href = @controller.url_for :controller => 'wiki', :web => web_address, :action => 'published',
+ :id => name
+ %{#{text}}
+ else
+ %{#{text}}
+ end
+ else
+ href = @controller.url_for :controller => 'wiki', :web => web_address, :action => 'file',
+ :id => name
+ if known_file
+ %{#{text}}
+ else
+ %{#{text}?}
end
end
end
- def make_page_link(mode, name, text, base_url, known_page)
- link = CGI.escape(name)
- case mode.to_sym
+ def page_link(mode, name, text, web_address, known_page)
+ case mode
when :export
- if known_page then %{#{text}}
- else %{#{text}} end
+ if known_page
+ %{#{text}}
+ else
+ %{#{text}}
+ end
when :publish
- if known_page then %{#{text}}
- else %{#{text}} end
+ if known_page
+ href = @controller.url_for :controller => 'wiki', :web => web_address, :action => 'published',
+ :id => name
+ %{#{text}}
+ else
+ %{#{text}}
+ end
else
if known_page
- %{#{text}}
+ href = @controller.url_for :controller => 'wiki', :web => web_address, :action => 'show',
+ :id => name
+ %{#{text}}
else
- %{#{text}?}
+ href = @controller.url_for :controller => 'wiki', :web => web_address, :action => 'new',
+ :id => name
+ %{#{text}?}
end
end
end
- def make_pic_link(mode, name, text, base_url, known_pic)
- link = CGI.escape(name)
- case mode.to_sym
+ def pic_link(mode, name, text, web_address, known_pic)
+ case mode
when :export
- if known_pic then %{}
- else %{} end
+ if known_pic
+ %{}
+ else
+ %{}
+ end
when :publish
- if known_pic then %{}
- else %{#{text}} end
+ if known_pic
+ %{}
+ else
+ %{#{text}}
+ end
else
- if known_pic then %{}
- else %{#{text}?} end
+ href = @controller.url_for @controller => 'file', :web => web_address, :action => 'pic',
+ :id => name
+ if known_pic
+ %{}
+ else
+ %{#{text}?}
+ end
end
end
end
-
-class ControllerStub
-end
\ No newline at end of file
diff --git a/lib/wiki_content.rb b/lib/wiki_content.rb
index 6fcc4a85..85816aba 100644
--- a/lib/wiki_content.rb
+++ b/lib/wiki_content.rb
@@ -126,8 +126,9 @@ class WikiContent < String
# Create a new wiki content string from the given one.
# The options are explained at the top of this file.
- def initialize(revision, options = {})
+ def initialize(revision, url_generator, options = {})
@revision = revision
+ @url_generator = url_generator
@web = @revision.page.web
@options = DEFAULT_OPTS.dup.merge(options)
@@ -146,7 +147,7 @@ class WikiContent < String
# Call @web.page_link using current options.
def page_link(name, text, link_type)
@options[:link_type] = (link_type || :show)
- @web.make_link(name, text, @options)
+ @url_generator.make_link(name, @web, text, @options)
end
def build_chunks
diff --git a/test/test_helper.rb b/test/test_helper.rb
index f310732a..928c2e49 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -11,6 +11,7 @@ require 'action_controller/test_process'
require 'action_web_service/test_invoke'
require 'breakpoint'
require 'wiki_content'
+require 'url_generator'
# Uncomment these and hang on, because the tests will be FAST
#Test::Unit::TestCase.pre_loaded_fixtures = false
@@ -43,6 +44,7 @@ class Test::Unit::TestCase
end
def test_renderer(revision = nil)
+ PageRenderer.setup_url_generator(StubUrlGenerator.new)
PageRenderer.new(revision)
end
@@ -93,6 +95,64 @@ module ChunkMatch
end
end
+class StubUrlGenerator < AbstractUrlGenerator
+
+ def initialize
+ super(:doesnt_need_controller)
+ end
+
+ def file_link(mode, name, text, web_name, known_file)
+ link = CGI.escape(name)
+ case mode
+ when :export
+ if known_file then %{#{text}}
+ else %{#{text}} end
+ when :publish
+ if known_file then %{#{text}}
+ else %{#{text}} end
+ else
+ if known_file
+ %{#{text}}
+ else
+ %{#{text}?}
+ end
+ end
+ end
+
+ def page_link(mode, name, text, web_address, known_page)
+ link = CGI.escape(name)
+ case mode.to_sym
+ when :export
+ if known_page then %{#{text}}
+ else %{#{text}} end
+ when :publish
+ if known_page then %{#{text}}
+ else %{#{text}} end
+ else
+ if known_page
+ %{#{text}}
+ else
+ %{#{text}?}
+ end
+ end
+ end
+
+ def pic_link(mode, name, text, web_name, known_pic)
+ link = CGI.escape(name)
+ case mode.to_sym
+ when :export
+ if known_pic then %{}
+ else %{} end
+ when :publish
+ if known_pic then %{}
+ else %{#{text}} end
+ else
+ if known_pic then %{}
+ else %{#{text}?} end
+ end
+ end
+end
+
if defined? $validate_xml_in_assert_success and $validate_xml_in_assert_success == true
module Test
module Unit
diff --git a/test/unit/page_renderer_test.rb b/test/unit/page_renderer_test.rb
index b94212fb..d84a74ff 100644
--- a/test/unit/page_renderer_test.rb
+++ b/test/unit/page_renderer_test.rb
@@ -25,50 +25,6 @@ class PageRendererTest < Test::Unit::TestCase
rendered_content(@web.page("SecondPage")))
end
- def test_make_link
- add_sample_pages
-
- existing_page_wiki_url =
- 'Ever Been In Love'
- existing_page_published_url =
- 'Ever Been In Love'
- existing_page_static_url =
- 'Ever Been In Love'
- new_page_wiki_url =
- 'Unknown Word?'
- new_page_published_url = new_page_static_url = 'Unknown Word'
-
- # no options
- assert_equal existing_page_wiki_url, @web.make_link('EverBeenInLove')
-
- # :mode => :export
- assert_equal existing_page_static_url, @web.make_link('EverBeenInLove', nil, :mode => :export)
-
- # :mode => :publish
- assert_equal existing_page_published_url,
- @web.make_link('EverBeenInLove', nil, :mode => :publish)
-
- # new page, no options
- assert_equal new_page_wiki_url, @web.make_link('UnknownWord')
-
- # new page, :mode => :export
- assert_equal new_page_static_url, @web.make_link('UnknownWord', nil, :mode => :export)
-
- # new page, :mode => :publish
- assert_equal new_page_published_url, @web.make_link('UnknownWord', nil, :mode => :publish)
-
- # Escaping special characters in the name
- assert_equal(
- 'Smith & Wesson?',
- @web.make_link('Smith & Wesson'))
-
- # optionally using text as the link text
- assert_equal(
- existing_page_published_url.sub(/>Ever Been In Love, ">Haven't you ever been in love?<"),
- @web.make_link('EverBeenInLove', "Haven't you ever been in love?", :mode => :publish))
-
- end
-
def test_wiki_words
assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ),
test_renderer(@revision).wiki_words.sort
diff --git a/test/watir/e2e.rb b/test/watir/e2e.rb
index cdf81554..4aeaf109 100644
--- a/test/watir/e2e.rb
+++ b/test/watir/e2e.rb
@@ -59,7 +59,7 @@ class E2EInstikiTest < Test::Unit::TestCase
def test_00020_add_a_page
# Add reference to a non-existant wiki page
enter_markup('HomePage', '[[Another Wiki Page]]')
- assert_equal '?', ie.link(:url, url(:show, 'Another Wiki Page')).text
+ assert_equal '?', ie.link(:url, url(:new, 'Another Wiki Page')).text
# Edit the first revision of a page
enter_markup('Another Wiki Page', 'First revision of Another Wiki Page, linked from HomePage')
From bfecd09b56993f80c703e0326afb530b3cc49332 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Sun, 11 Sep 2005 04:23:50 +0000
Subject: [PATCH 46/84] Fixed includes; started wrking onn caching strategy
---
app/controllers/wiki_controller.rb | 3 ++
config/environments/production.rb | 3 +-
lib/chunks/include.rb | 11 +++---
lib/chunks/wiki.rb | 7 +---
script/import_storage | 61 ++++++++++++++++++++----------
test/watir/e2e.rb | 5 +++
6 files changed, 58 insertions(+), 32 deletions(-)
diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb
index 63b3a988..65a67aa6 100644
--- a/app/controllers/wiki_controller.rb
+++ b/app/controllers/wiki_controller.rb
@@ -5,6 +5,9 @@ require 'zip/zip'
class WikiController < ApplicationController
+ # TODO implement cache sweeping
+ caches_page :show
+
layout 'default', :except => [:rss_feed, :rss_with_content, :rss_with_headlines, :tex, :export_tex, :export_html]
def index
diff --git a/config/environments/production.rb b/config/environments/production.rb
index e5b18783..80c7661f 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -1,4 +1,3 @@
Dependencies.mechanism = :require
ActionController::Base.consider_all_requests_local = false
-ActionController::Base.perform_caching = false
-
+ActionController::Base.perform_caching = true
diff --git a/lib/chunks/include.rb b/lib/chunks/include.rb
index 370093cc..90dc02a7 100644
--- a/lib/chunks/include.rb
+++ b/lib/chunks/include.rb
@@ -22,16 +22,17 @@ class Include < WikiChunk::WikiReference
private
def get_unmask_text_avoiding_recursion_loops
- if refpage then
- refpage.clear_display_cache
- if refpage.wiki_includes.include?(@content.page_name)
+ if refpage
+ # TODO This way of instantiating a renderer is ugly.
+ renderer = PageRenderer.new(refpage.current_revision)
+ if renderer.wiki_includes.include?(@content.page_name)
# this will break the recursion
@content.delete_chunk(self)
return "Recursive include detected; #{@page_name} --> #{@content.page_name} " +
"--> #{@page_name}\n"
else
- @content.merge_chunks(refpage.display_content)
- return refpage.display_content.pre_rendered
+ @content.merge_chunks(renderer.display_content)
+ return renderer.display_content.pre_rendered
end
else
return "Could not include #{@page_name}\n"
diff --git a/lib/chunks/wiki.rb b/lib/chunks/wiki.rb
index 840f644a..07d74600 100644
--- a/lib/chunks/wiki.rb
+++ b/lib/chunks/wiki.rb
@@ -16,7 +16,7 @@ module WikiChunk
# the referenced page
def refpage
- @content.web.pages[@page_name]
+ @content.web.page(@page_name)
end
end
@@ -45,11 +45,6 @@ module WikiChunk
end
end
- # the referenced page
- def refpage
- @content.web.pages[@page_name]
- end
-
def textile_url?
not @textile_link_suffix.nil?
end
diff --git a/script/import_storage b/script/import_storage
index 2659defd..c257004f 100755
--- a/script/import_storage
+++ b/script/import_storage
@@ -5,6 +5,7 @@ require 'optparse'
OPTIONS = {
:instiki_root => nil,
:storage => nil,
+ :database => 'mysql'
}
ARGV.options do |opts|
@@ -38,6 +39,12 @@ ARGV.options do |opts|
OPTIONS[:outfile] = outfile
end
+ opts.on("-d", "--database {mysql|sqlite|postgres}", String,
+ "Target database (they have slightly different syntax)",
+ "default: mysql") do |database|
+ OPTIONS[:database] = database
+ end
+
opts.separator ""
opts.on_tail("-h", "--help",
@@ -95,15 +102,29 @@ class Revision
end
end
+class Time
+ def ansi
+ strftime('%Y-%m-%d %H:%M:%S')
+ end
+end
+
def sql_insert(table, hash)
output = "INSERT INTO #{table} ("
output << hash.keys.join(", ")
output << ") VALUES ('"
- output << hash.values.map{|v| v.to_s.gsub("'", "\\\\'")}.join("', '")
-
+ output << hash.values.map do |v|
+ case OPTIONS[:database]
+ when 'mysql', 'postgres'
+ v.to_s.gsub("'", "\\\\'")
+ when 'sqlite'
+ v.to_s.gsub("'", "''")
+ else
+ raise "Unsupported database option #{OPTIONS[:database]}"
+ end
+ end.join("', '")
output << "');"
- return output
+ output
end
WikiService.storage_path = OPTIONS[:storage]
@@ -125,34 +146,36 @@ File.open(OPTIONS[:outfile], 'w') { |outfile|
:max_upload_size => web.max_upload_size,
:safe_mode => web.safe_mode,
:brackets_only => web.brackets_only,
+ :created_at => web.pages.values.map { |p| p.revisions.first.created_at }.min.ansi,
+ :updated_at => web.pages.values.map { |p| p.revisions.last.created_at }.max.ansi
})
puts "Web #{web_name} has #{web.pages.keys.size} pages"
web.pages.each_pair do |page_name, page|
outfile.puts sql_insert(:pages, {
- :id => page.object_id,
- :web_id => web.object_id,
- :locked_by => page.locked_by,
- :name => page.name
+ :id => page.object_id,
+ :web_id => web.object_id,
+ :locked_by => page.locked_by,
+ :name => page.name,
+ :created_at => page.revisions.first.created_at.ansi,
+ :updated_at => page.revisions.last.created_at.ansi
})
puts " Page #{page_name} has #{page.revisions.size} revisions"
page.revisions.each_with_index do |rev, i|
+
outfile.puts sql_insert(:revisions, {
- :id => rev.object_id,
- :page_id => page.object_id,
- :content => rev.content,
- :author => rev.author,
- :ip => '0.0.0.0',
+ :id => rev.object_id,
+ :page_id => page.object_id,
+ :content => rev.content,
+ :author => rev.author.to_s,
+ :ip => (rev.author.is_a?(Author) ? rev.author.ip : 'N/A'),
+ :created_at => rev.created_at.ansi,
+ :updated_at => rev.created_at.ansi,
+ :revised_at => rev.created_at.ansi
})
- puts " Revision #{i} created at #{rev.created_at}"
+ puts " Revision #{i} created at #{rev.created_at.ansi}"
end
end
end
-
- ['webs', 'pages', 'revisions'].each do |table|
- outfile.puts "UPDATE #{table} SET created_at = NOW();"
- outfile.puts "UPDATE #{table} SET updated_at = NOW();"
- end
- outfile.puts "UPDATE revisions SET revised_at = NOW();"
}
diff --git a/test/watir/e2e.rb b/test/watir/e2e.rb
index 4aeaf109..95c43d6a 100644
--- a/test/watir/e2e.rb
+++ b/test/watir/e2e.rb
@@ -6,6 +6,11 @@ require 'rexml/document'
INSTIKI_ROOT = File.expand_path(File.dirname(__FILE__) + "/../..")
require(File.expand_path(File.dirname(__FILE__) + "/../../config/environment"))
+# TODO Create tests for:
+# * exporting HTML
+# * exporting markup
+# * include tag
+
# Use instiki/../watir, if such a directory exists; This can be a CVS HEAD version of Watir.
# Otherwise Watir has to be installed in ruby/lib.
$:.unshift INSTIKI_ROOT + '/../watir' if File.exists?(INSTIKI_ROOT + '/../watir/watir.rb')
From cd68db01d2f8cd438ff33f9ca13a0483aa97fb23 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Sun, 11 Sep 2005 05:44:34 +0000
Subject: [PATCH 47/84] Store wiki references found during rendering
---
app/controllers/wiki_controller.rb | 2 +-
app/models/page.rb | 3 +-
lib/chunks/include.rb | 1 -
lib/page_renderer.rb | 104 +++++++++++++----------------
test/unit/page_renderer_test.rb | 14 +++-
5 files changed, 61 insertions(+), 63 deletions(-)
diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb
index 65a67aa6..efe89ef2 100644
--- a/app/controllers/wiki_controller.rb
+++ b/app/controllers/wiki_controller.rb
@@ -6,7 +6,7 @@ require 'zip/zip'
class WikiController < ApplicationController
# TODO implement cache sweeping
- caches_page :show
+ caches_page :show, :published
layout 'default', :except => [:rss_feed, :rss_with_content, :rss_with_headlines, :tex, :export_tex, :export_html]
diff --git a/app/models/page.rb b/app/models/page.rb
index 7d0e8695..715ac6ce 100644
--- a/app/models/page.rb
+++ b/app/models/page.rb
@@ -1,6 +1,7 @@
class Page < ActiveRecord::Base
belongs_to :web
has_many :revisions, :order => 'id'
+ has_many :wiki_references, :order => 'referenced_page_name'
has_one :current_revision, :class_name => 'Revision', :order => 'id DESC'
def revise(content, time, author, renderer)
@@ -15,7 +16,7 @@ class Page < ActiveRecord::Base
# Try to render content to make sure that markup engine can take it,
renderer.revision = Revision.new(
:page => self, :content => content, :author => author, :revised_at => time)
- renderer.force_rendering
+ renderer.display_content
# A user may change a page, look at it and make some more changes - several times.
# Not to record every such iteration as a new revision, if the previous revision was done
diff --git a/lib/chunks/include.rb b/lib/chunks/include.rb
index 90dc02a7..72c89b54 100644
--- a/lib/chunks/include.rb
+++ b/lib/chunks/include.rb
@@ -12,7 +12,6 @@ class Include < WikiChunk::WikiReference
INCLUDE_PATTERN = /\[\[!include\s+(.*?)\]\]\s*/i
def self.pattern() INCLUDE_PATTERN end
-
def initialize(match_data, content)
super
@page_name = match_data[1].strip
diff --git a/lib/page_renderer.rb b/lib/page_renderer.rb
index db10730a..39b28052 100644
--- a/lib/page_renderer.rb
+++ b/lib/page_renderer.rb
@@ -12,11 +12,37 @@ class PageRenderer
@@url_generator = nil
end
- attr_accessor :revision
-
+ attr_reader :revision
def initialize(revision = nil)
- @revision = revision
+ self.revision = revision
+ end
+
+ def revision=(r)
+ @revision = r
+ @wiki_words_cache = @wiki_includes_cache = @wiki_references_cache = nil
+ end
+
+ def display_content
+ render
+ end
+
+ def display_content_for_export
+ render :mode => :export
+ end
+
+ def display_published
+ render :mode => :publish
+ end
+
+ def display_diff
+ previous_revision = @revision.page.previous_revision(@revision)
+ if previous_revision
+ rendered_previous_revision = WikiContent.new(previous_revision, @@url_generator).render!
+ HTMLDiff.diff(rendered_previous_revision, display_content)
+ else
+ display_content
+ end
end
# Returns an array of all the WikiIncludes present in the content of this revision.
@@ -35,7 +61,7 @@ class PageRenderer
@wiki_references_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
end
@wiki_references_cache
- end
+ end
# Returns an array of all the WikiWords present in the content of this revision.
def wiki_words
@@ -58,61 +84,21 @@ class PageRenderer
wiki_words - existing_pages
end
- # Explicit check for new type of display cache with chunks_by_type method.
- # Ensures new version works with older snapshots.
- def display_content
- unless @display_cache && @display_cache.respond_to?(:chunks_by_type)
- @display_cache = WikiContent.new(@revision, @@url_generator)
- @display_cache.render!
- end
- @display_cache
- end
-
- # TODO this probably doesn't belong in revision (because it has to call back the page)
- def display_diff
- previous_revision = @revision.page.previous_revision(@revision)
- if previous_revision
- HTMLDiff.diff(PageRenderer.new(previous_revision).display_content, display_content)
- else
- display_content
- end
- end
-
- def clear_display_cache
- @wiki_words_cache = @published_cache = @display_cache = @wiki_includes_cache =
- @wiki_references_cache = nil
- end
-
- def display_published
- unless @published_cache && @published_cache.respond_to?(:chunks_by_type)
- @published_cache = WikiContent.new(@revision, @@url_generator, {:mode => :publish})
- @published_cache.render!
- end
- @published_cache
- end
-
- def display_content_for_export
- WikiContent.new(@revision, @@url_generator, {:mode => :export} ).render!
- end
+ private
- def force_rendering
- begin
- display_content.render!
- rescue => e
- ActionController::Base.logger.error "Failed rendering page #{@name}"
- ActionController::Base.logger.error e
- message = e.message
- # substitute content with an error message
- @revision.content = <<-EOL
-
Markup engine has failed to render this page, raising the following error:
-
#{message}
-
#{@revision.content}
- EOL
- clear_display_cache
- raise e
+ def render(options = {})
+ result = WikiContent.new(@revision, @@url_generator, options).render!
+ @revision.page.wiki_references.delete
+
+ wiki_word_chunks = result.find_chunks(WikiChunk::WikiLink)
+ wiki_words = wiki_word_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
+
+ wiki_words.each do |referenced_page_name|
+ @revision.page.wiki_references.create({
+ :referenced_page_name => referenced_page_name,
+ :link_type => WikiReference.link_type(@revision.page.web, referenced_page_name)
+ })
end
+ result
end
-
- protected
-
-end
\ No newline at end of file
+end
diff --git a/test/unit/page_renderer_test.rb b/test/unit/page_renderer_test.rb
index d84a74ff..e04540c8 100644
--- a/test/unit/page_renderer_test.rb
+++ b/test/unit/page_renderer_test.rb
@@ -1,7 +1,7 @@
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
class PageRendererTest < Test::Unit::TestCase
- fixtures :webs, :pages, :revisions, :system
+ fixtures :webs, :pages, :revisions, :system, :wiki_references
def setup
@wiki = Wiki.new
@@ -325,6 +325,18 @@ class PageRendererTest < Test::Unit::TestCase
"!http://google.com!\r\nss")
end
+
+ # Tests for the caching of wiki references and categories
+ def test_references_creation
+ new_page = @web.add_page('NewPage', 'HomePage',
+ Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', test_renderer)
+
+ references = new_page.wiki_references(true)
+ assert_equal 1, references.size
+ assert_equal 'HomePage', references[0].referenced_page_name
+ assert_equal WikiReference::LINKED_PAGE, references[0].link_type
+ end
+
private
def add_sample_pages
From 0c6626c3750aeda458dadc9033817eb2294c92f9 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Sun, 11 Sep 2005 05:59:21 +0000
Subject: [PATCH 48/84] Corrected WikiReference::link_type when a newly created
page refers to itself (should be 'L', not 'W')
---
lib/page_renderer.rb | 8 +++++++-
test/unit/page_renderer_test.rb | 9 +++++++--
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/lib/page_renderer.rb b/lib/page_renderer.rb
index 39b28052..23ab3e79 100644
--- a/lib/page_renderer.rb
+++ b/lib/page_renderer.rb
@@ -94,9 +94,15 @@ class PageRenderer
wiki_words = wiki_word_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
wiki_words.each do |referenced_page_name|
+ # Links to self are always considered linked
+ if referenced_page_name == @revision.page.name
+ link_type = WikiReference::LINKED_PAGE
+ else
+ link_type = WikiReference.link_type(@revision.page.web, referenced_page_name)
+ end
@revision.page.wiki_references.create({
:referenced_page_name => referenced_page_name,
- :link_type => WikiReference.link_type(@revision.page.web, referenced_page_name)
+ :link_type => link_type
})
end
result
diff --git a/test/unit/page_renderer_test.rb b/test/unit/page_renderer_test.rb
index e04540c8..0a555e34 100644
--- a/test/unit/page_renderer_test.rb
+++ b/test/unit/page_renderer_test.rb
@@ -328,13 +328,18 @@ class PageRendererTest < Test::Unit::TestCase
# Tests for the caching of wiki references and categories
def test_references_creation
- new_page = @web.add_page('NewPage', 'HomePage',
+ new_page = @web.add_page('NewPage', 'HomePage NewPage',
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', test_renderer)
references = new_page.wiki_references(true)
- assert_equal 1, references.size
+ assert_equal 2, references.size
assert_equal 'HomePage', references[0].referenced_page_name
assert_equal WikiReference::LINKED_PAGE, references[0].link_type
+ assert_equal 'NewPage', references[1].referenced_page_name
+ assert_equal WikiReference::LINKED_PAGE, references[1].link_type
+ end
+
+ def test_rendering_changes_references_from_wanted_to_linked
end
private
From 6ff74f6b5acbaa2e16ba340653f1ee5fd5c3d423 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Sun, 11 Sep 2005 06:15:59 +0000
Subject: [PATCH 49/84] Update wiki_references to a newly created page from 'W'
to 'L'
---
app/models/page.rb | 4 ++++
test/unit/page_renderer_test.rb | 21 +++++++++++++++++++++
2 files changed, 25 insertions(+)
diff --git a/app/models/page.rb b/app/models/page.rb
index 715ac6ce..44d76102 100644
--- a/app/models/page.rb
+++ b/app/models/page.rb
@@ -4,6 +4,10 @@ class Page < ActiveRecord::Base
has_many :wiki_references, :order => 'referenced_page_name'
has_one :current_revision, :class_name => 'Revision', :order => 'id DESC'
+ def before_create
+ WikiReference.register_page_creation(self)
+ end
+
def revise(content, time, author, renderer)
revisions_size = new_record? ? 0 : revisions.size
if (revisions_size > 0) and content == current_revision.content
diff --git a/test/unit/page_renderer_test.rb b/test/unit/page_renderer_test.rb
index 0a555e34..c8bbeb92 100644
--- a/test/unit/page_renderer_test.rb
+++ b/test/unit/page_renderer_test.rb
@@ -340,6 +340,27 @@ class PageRendererTest < Test::Unit::TestCase
end
def test_rendering_changes_references_from_wanted_to_linked
+ new_page = @web.add_page('NewPage', 'Reference to WantedPage, and to WantedPage2',
+ Time.now, 'AlexeyVerkhovsky', test_renderer)
+
+ references = new_page.wiki_references(true)
+ assert_equal 2, references.size
+ assert_equal 'WantedPage', references[0].referenced_page_name
+ assert_equal WikiReference::WANTED_PAGE, references[0].link_type
+ assert_equal 'WantedPage2', references[1].referenced_page_name
+ assert_equal WikiReference::WANTED_PAGE, references[1].link_type
+
+ wanted_page = @web.add_page('WantedPage', 'And here it is!',
+ Time.now, 'AlexeyVerkhovsky', test_renderer)
+
+ # link type stored for NewPage -> WantedPage reference should change from WANTED to LINKED
+ # reference NewPage -> WantedPage2 should remain the same
+ references = new_page.wiki_references(true)
+ assert_equal 2, references.size
+ assert_equal 'WantedPage', references[0].referenced_page_name
+ assert_equal WikiReference::LINKED_PAGE, references[0].link_type
+ assert_equal 'WantedPage2', references[1].referenced_page_name
+ assert_equal WikiReference::WANTED_PAGE, references[1].link_type
end
private
From bec3c98227ad8be506ec02073049669b136cb188 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Sun, 11 Sep 2005 06:28:59 +0000
Subject: [PATCH 50/84] Moved the last unit test where it belongs
---
test/unit/page_renderer_test.rb | 24 ------------------------
test/unit/page_test.rb | 28 ++++++++++++++++++++++++++++
2 files changed, 28 insertions(+), 24 deletions(-)
diff --git a/test/unit/page_renderer_test.rb b/test/unit/page_renderer_test.rb
index c8bbeb92..32c172db 100644
--- a/test/unit/page_renderer_test.rb
+++ b/test/unit/page_renderer_test.rb
@@ -339,30 +339,6 @@ class PageRendererTest < Test::Unit::TestCase
assert_equal WikiReference::LINKED_PAGE, references[1].link_type
end
- def test_rendering_changes_references_from_wanted_to_linked
- new_page = @web.add_page('NewPage', 'Reference to WantedPage, and to WantedPage2',
- Time.now, 'AlexeyVerkhovsky', test_renderer)
-
- references = new_page.wiki_references(true)
- assert_equal 2, references.size
- assert_equal 'WantedPage', references[0].referenced_page_name
- assert_equal WikiReference::WANTED_PAGE, references[0].link_type
- assert_equal 'WantedPage2', references[1].referenced_page_name
- assert_equal WikiReference::WANTED_PAGE, references[1].link_type
-
- wanted_page = @web.add_page('WantedPage', 'And here it is!',
- Time.now, 'AlexeyVerkhovsky', test_renderer)
-
- # link type stored for NewPage -> WantedPage reference should change from WANTED to LINKED
- # reference NewPage -> WantedPage2 should remain the same
- references = new_page.wiki_references(true)
- assert_equal 2, references.size
- assert_equal 'WantedPage', references[0].referenced_page_name
- assert_equal WikiReference::LINKED_PAGE, references[0].link_type
- assert_equal 'WantedPage2', references[1].referenced_page_name
- assert_equal WikiReference::WANTED_PAGE, references[1].link_type
- end
-
private
def add_sample_pages
diff --git a/test/unit/page_test.rb b/test/unit/page_test.rb
index 8b63f67a..e466b926 100644
--- a/test/unit/page_test.rb
+++ b/test/unit/page_test.rb
@@ -7,6 +7,7 @@ class PageTest < Test::Unit::TestCase
@page = pages(:first_page)
end
+
def test_lock
assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
@@ -84,6 +85,33 @@ class PageTest < Test::Unit::TestCase
assert_equal revisions_number_before, @page.revisions.size
end
+ def test_revise_changes_references_from_wanted_to_linked_for_new_pages
+ web = Web.find(1)
+ new_page = Page.new(:web => web, :name => 'NewPage')
+ new_page.revise('Reference to WantedPage, and to WantedPage2', Time.now, 'AlexeyVerkhovsky',
+ test_renderer)
+
+ references = new_page.wiki_references(true)
+ assert_equal 2, references.size
+ assert_equal 'WantedPage', references[0].referenced_page_name
+ assert_equal WikiReference::WANTED_PAGE, references[0].link_type
+ assert_equal 'WantedPage2', references[1].referenced_page_name
+ assert_equal WikiReference::WANTED_PAGE, references[1].link_type
+
+ wanted_page = Page.new(:web => web, :name => 'WantedPage')
+ wanted_page.revise('And here it is!', Time.now, 'AlexeyVerkhovsky', test_renderer)
+
+ # link type stored for NewPage -> WantedPage reference should change from WANTED to LINKED
+ # reference NewPage -> WantedPage2 should remain the same
+ references = new_page.wiki_references(true)
+ assert_equal 2, references.size
+ assert_equal 'WantedPage', references[0].referenced_page_name
+ assert_equal WikiReference::LINKED_PAGE, references[0].link_type
+ assert_equal 'WantedPage2', references[1].referenced_page_name
+ assert_equal WikiReference::WANTED_PAGE, references[1].link_type
+ end
+
+
def test_rollback
@page.revise("spot two", Time.now, "David", test_renderer)
@page.revise("spot three", Time.now + 2000, "David", test_renderer)
From 541a5d39942cd74aced59ef7dde2a3c3fd61da67 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Sun, 11 Sep 2005 08:05:19 +0000
Subject: [PATCH 51/84] Deleted all references to PageRenderer from PageSet
selectors; using wiki_references instead
---
app/controllers/application.rb | 2 ++
app/models/page.rb | 4 ----
app/models/page_set.rb | 11 +++++++----
test/functional/admin_controller_test.rb | 3 +--
test/functional/wiki_controller_test.rb | 2 +-
test/test_helper.rb | 3 +++
test/unit/web_test.rb | 4 ++--
7 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/app/controllers/application.rb b/app/controllers/application.rb
index 2208066a..05fb89ce 100644
--- a/app/controllers/application.rb
+++ b/app/controllers/application.rb
@@ -5,6 +5,8 @@ class ApplicationController < ActionController::Base
before_filter :set_utf8_http_header, :connect_to_model, :setup_url_generator
after_filter :remember_location, :teardown_url_generator
+ observer :page_observer
+
# For injecting a different wiki model implementation. Intended for use in tests
def self.wiki=(the_wiki)
# a global variable is used here because Rails reloads controller and model classes in the
diff --git a/app/models/page.rb b/app/models/page.rb
index 44d76102..715ac6ce 100644
--- a/app/models/page.rb
+++ b/app/models/page.rb
@@ -4,10 +4,6 @@ class Page < ActiveRecord::Base
has_many :wiki_references, :order => 'referenced_page_name'
has_one :current_revision, :class_name => 'Revision', :order => 'id DESC'
- def before_create
- WikiReference.register_page_creation(self)
- end
-
def revise(content, time, author, renderer)
revisions_size = new_record? ? 0 : revisions.size
if (revisions_size > 0) and content == current_revision.content
diff --git a/app/models/page_set.rb b/app/models/page_set.rb
index 9fd43ca9..d806e5a8 100644
--- a/app/models/page_set.rb
+++ b/app/models/page_set.rb
@@ -31,15 +31,18 @@ class PageSet < Array
end
def pages_that_reference(page_name)
- self.select { |page| PageRenderer.new(page.revisions.last).wiki_references.include?(page_name) }
+ all_referring_pages = WikiReference.pages_that_reference(page_name)
+ self.select { |page| all_referring_pages.include?(page.name) }
end
def pages_that_link_to(page_name)
- self.select { |page| PageRenderer.new(page.revisions.last).wiki_words.include?(page_name) }
+ all_linking_pages = WikiReference.pages_that_link_to(page_name)
+ self.select { |page| all_linking_pages.include?(page.name) }
end
def pages_that_include(page_name)
- self.select { |page| PageRenderer.new(page.revisions.last).wiki_includes.include?(page_name) }
+ all_including_pages = WikiReference.pages_that_include(page_name)
+ self.select { |page| all_including_pages.include?(page.name) }
end
def pages_authored_by(author)
@@ -78,7 +81,7 @@ class PageSet < Array
end
def wiki_words
- self.inject([]) { |wiki_words, page| wiki_words << PageRenderer.new(page.revisions.last).wiki_words }.flatten.uniq
+ self.inject([]) { |wiki_words, page| WikiReference.wiki_words(page) }.flatten.uniq
end
def authors
diff --git a/test/functional/admin_controller_test.rb b/test/functional/admin_controller_test.rb
index 886041fd..6df919f3 100644
--- a/test/functional/admin_controller_test.rb
+++ b/test/functional/admin_controller_test.rb
@@ -7,7 +7,7 @@ require 'admin_controller'
class AdminController; def rescue_action(e) logger.error(e); raise e end; end
class AdminControllerTest < Test::Unit::TestCase
- fixtures :webs, :pages, :revisions, :system
+ fixtures :webs, :pages, :revisions, :system, :wiki_references
def setup
@controller = AdminController.new
@@ -204,7 +204,6 @@ class AdminControllerTest < Test::Unit::TestCase
assert_equal page_order, @web.select.sort,
"Pages are not as expected: #{@web.select.sort.map {|p| p.name}.inspect}"
-
# Oak is now orphan, second pass should remove it
r = process('remove_orphaned_pages', 'web' => 'wiki1', 'system_password_orphaned' => 'pswd')
assert_redirected_to :controller => 'wiki', :web => 'wiki1', :action => 'list'
diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb
index ea33e717..54c541b3 100755
--- a/test/functional/wiki_controller_test.rb
+++ b/test/functional/wiki_controller_test.rb
@@ -14,7 +14,7 @@ require 'zip/zipfilesystem'
class WikiController; def rescue_action(e) logger.error(e); raise e end; end
class WikiControllerTest < Test::Unit::TestCase
- fixtures :webs, :pages, :revisions, :system
+ fixtures :webs, :pages, :revisions, :system, :wiki_references
def setup
@controller = WikiController.new
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 928c2e49..adf78cf2 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -20,6 +20,9 @@ require 'url_generator'
Test::Unit::TestCase.use_instantiated_fixtures = false
Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
+# activate PageObserver
+PageObserver.instance
+
class Test::Unit::TestCase
def create_fixtures(*table_names)
Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures", table_names)
diff --git a/test/unit/web_test.rb b/test/unit/web_test.rb
index ea08523a..875c0bb3 100644
--- a/test/unit/web_test.rb
+++ b/test/unit/web_test.rb
@@ -1,7 +1,7 @@
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
class WebTest < Test::Unit::TestCase
- fixtures :webs, :pages, :revisions, :system
+ fixtures :webs, :pages, :revisions, :system, :wiki_references
def setup
@web = webs(:instiki)
@@ -78,7 +78,7 @@ class WebTest < Test::Unit::TestCase
'This is an author page, it should not be an orphan',
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', test_renderer)
self_linked = @web.add_page('SelfLinked',
- 'I am me SelfLinked and link to EverBeenInLove',
+ 'I am SelfLinked and link to EverBeenInLove',
Time.local(2004, 4, 4, 16, 50), 'AnonymousCoward', test_renderer)
# page that links to itself, and nobody else links to it must be an orphan
From ac819d4d682d735fc667ce73e255b60a3dd2ba60 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Sun, 11 Sep 2005 09:34:41 +0000
Subject: [PATCH 52/84] BREAKS BUILD: all pages etc are much faster, but
categories functionality is broken (it was responsible for calling the
renderer once per every page on All Pages)
---
app/controllers/wiki_controller.rb | 4 +++-
app/models/page_set.rb | 4 +++-
app/models/web.rb | 2 +-
lib/page_renderer.rb | 1 +
4 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb
index efe89ef2..be93de83 100644
--- a/app/controllers/wiki_controller.rb
+++ b/app/controllers/wiki_controller.rb
@@ -291,7 +291,9 @@ class WikiController < ApplicationController
@category = @params['category']
@categories = []
@pages_in_category = @web.select do |page|
- page_categories = PageRenderer.new(page.revisions.last).display_content.find_chunks(Category)
+ # FIXME: was PageRenderer.new(page.revisions.last).display_content.find_chunks(Category),
+ # heinously slow
+ page_categories = []
page_categories = page_categories.map { |cat| cat.list }.flatten
page_categories.each {|c| @categories << c unless @categories.include? c }
page_categories.include?(@category)
diff --git a/app/models/page_set.rb b/app/models/page_set.rb
index d806e5a8..6a9b2700 100644
--- a/app/models/page_set.rb
+++ b/app/models/page_set.rb
@@ -81,7 +81,9 @@ class PageSet < Array
end
def wiki_words
- self.inject([]) { |wiki_words, page| WikiReference.wiki_words(page) }.flatten.uniq
+ self.inject([]) { |wiki_words, page|
+ wiki_words + page.wiki_references.map { |ref| ref.referenced_page_name }
+ }.flatten.uniq
end
def authors
diff --git a/app/models/web.rb b/app/models/web.rb
index e3b2f7d0..62f88623 100644
--- a/app/models/web.rb
+++ b/app/models/web.rb
@@ -1,5 +1,5 @@
class Web < ActiveRecord::Base
- has_many :pages#, :include => [:current_revision, :web]
+ has_many :pages
def wiki
Wiki.new
diff --git a/lib/page_renderer.rb b/lib/page_renderer.rb
index 23ab3e79..61428bd2 100644
--- a/lib/page_renderer.rb
+++ b/lib/page_renderer.rb
@@ -88,6 +88,7 @@ class PageRenderer
def render(options = {})
result = WikiContent.new(@revision, @@url_generator, options).render!
+ WikiReference.delete_all ['page_id = ?', @revision.page_id]
@revision.page.wiki_references.delete
wiki_word_chunks = result.find_chunks(WikiChunk::WikiLink)
From 32d238098ef4ed7b4b8b48e13b8d849aff5b2965 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Sun, 11 Sep 2005 14:03:08 +0000
Subject: [PATCH 53/84] Taking care of svn adds and svn deletes for the last 24
hours or so. Boo on me!
---
Rakefile | 202 ------------------------------
app/models/page_observer.rb | 15 +++
app/models/wiki_reference.rb | 50 ++++++++
db/wiki_references.erbsql | 9 ++
lib/page_renderer.rb | 17 ++-
script/reset_references | 25 ++++
test/fixtures/wiki_references.yml | 95 ++++++++++++++
test/unit/page_renderer_test.rb | 13 +-
8 files changed, 216 insertions(+), 210 deletions(-)
delete mode 100644 Rakefile
create mode 100644 app/models/page_observer.rb
create mode 100644 app/models/wiki_reference.rb
create mode 100644 db/wiki_references.erbsql
create mode 100644 script/reset_references
create mode 100644 test/fixtures/wiki_references.yml
diff --git a/Rakefile b/Rakefile
deleted file mode 100644
index 5407e140..00000000
--- a/Rakefile
+++ /dev/null
@@ -1,202 +0,0 @@
-require 'rake'
-require 'rake/testtask'
-require 'rake/rdoctask'
-
-$VERBOSE = nil
-TEST_CHANGES_SINCE = Time.now - 600
-
-desc "Run all the tests on a fresh test database"
-task :default => [ :test_units, :test_functional ]
-
-
-desc 'Require application environment.'
-task :environment do
- unless defined? RAILS_ROOT
- require File.dirname(__FILE__) + '/config/environment'
- end
-end
-
-desc "Generate API documentation, show coding stats"
-task :doc => [ :appdoc, :stats ]
-
-
-# Look up tests for recently modified sources.
-def recent_tests(source_pattern, test_path, touched_since = 10.minutes.ago)
- FileList[source_pattern].map do |path|
- if File.mtime(path) > touched_since
- test = "#{test_path}/#{File.basename(path, '.rb')}_test.rb"
- test if File.exists?(test)
- end
- end.compact
-end
-
-desc 'Test recent changes.'
-Rake::TestTask.new(:recent => [ :clone_structure_to_test ]) do |t|
- since = TEST_CHANGES_SINCE
- touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } +
- recent_tests('app/models/*.rb', 'test/unit', since) +
- recent_tests('app/controllers/*.rb', 'test/functional', since)
-
- t.libs << 'test'
- t.verbose = true
- t.test_files = touched.uniq
-end
-task :test_recent => [ :clone_structure_to_test ]
-
-desc "Run the unit tests in test/unit"
-Rake::TestTask.new("test_units") { |t|
- t.libs << "test"
- t.pattern = 'test/unit/**/*_test.rb'
- t.verbose = true
-}
-task :test_units => [ :clone_structure_to_test ]
-
-desc "Run the functional tests in test/functional"
-Rake::TestTask.new("test_functional") { |t|
- t.libs << "test"
- t.pattern = 'test/functional/**/*_test.rb'
- t.verbose = true
-}
-task :test_functional => [ :clone_structure_to_test ]
-
-desc "Generate documentation for the application"
-Rake::RDocTask.new("appdoc") { |rdoc|
- rdoc.rdoc_dir = 'doc/app'
- rdoc.title = "Rails Application Documentation"
- rdoc.options << '--line-numbers --inline-source'
- rdoc.rdoc_files.include('doc/README_FOR_APP')
- rdoc.rdoc_files.include('app/**/*.rb')
-}
-
-desc "Generate documentation for the Rails framework"
-Rake::RDocTask.new("apidoc") { |rdoc|
- rdoc.rdoc_dir = 'doc/api'
- rdoc.template = "#{ENV['template']}.rb" if ENV['template']
- rdoc.title = "Rails Framework Documentation"
- rdoc.options << '--line-numbers --inline-source'
- rdoc.rdoc_files.include('README')
- rdoc.rdoc_files.include('CHANGELOG')
- rdoc.rdoc_files.include('vendor/rails/railties/CHANGELOG')
- rdoc.rdoc_files.include('vendor/rails/railties/MIT-LICENSE')
- rdoc.rdoc_files.include('vendor/rails/activerecord/README')
- rdoc.rdoc_files.include('vendor/rails/activerecord/CHANGELOG')
- rdoc.rdoc_files.include('vendor/rails/activerecord/lib/active_record/**/*.rb')
- rdoc.rdoc_files.exclude('vendor/rails/activerecord/lib/active_record/vendor/*')
- rdoc.rdoc_files.include('vendor/rails/actionpack/README')
- rdoc.rdoc_files.include('vendor/rails/actionpack/CHANGELOG')
- rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_controller/**/*.rb')
- rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_view/**/*.rb')
- rdoc.rdoc_files.include('vendor/rails/actionmailer/README')
- rdoc.rdoc_files.include('vendor/rails/actionmailer/CHANGELOG')
- rdoc.rdoc_files.include('vendor/rails/actionmailer/lib/action_mailer/base.rb')
- rdoc.rdoc_files.include('vendor/rails/actionwebservice/README')
- rdoc.rdoc_files.include('vendor/rails/actionwebservice/CHANGELOG')
- rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service.rb')
- rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/*.rb')
- rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/api/*.rb')
- rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/client/*.rb')
- rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/container/*.rb')
- rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/dispatcher/*.rb')
- rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/protocol/*.rb')
- rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/support/*.rb')
- rdoc.rdoc_files.include('vendor/rails/activesupport/README')
- rdoc.rdoc_files.include('vendor/rails/activesupport/CHANGELOG')
- rdoc.rdoc_files.include('vendor/rails/activesupport/lib/active_support/**/*.rb')
-}
-
-desc "Report code statistics (KLOCs, etc) from the application"
-task :stats => [ :environment ] do
- require 'code_statistics'
- CodeStatistics.new(
- ["Helpers", "app/helpers"],
- ["Controllers", "app/controllers"],
- ["APIs", "app/apis"],
- ["Components", "components"],
- ["Functionals", "test/functional"],
- ["Models", "app/models"],
- ["Units", "test/unit"]
- ).to_s
-end
-
-desc "Recreate the test databases from the development structure"
-task :clone_structure_to_test => [ :db_structure_dump, :purge_test_database ] do
- abcs = ActiveRecord::Base.configurations
- case abcs["test"]["adapter"]
- when "mysql"
- ActiveRecord::Base.establish_connection(:test)
- ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
- IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table|
- ActiveRecord::Base.connection.execute(table)
- end
- when "postgresql"
- ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
- ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
- ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
- `psql -U "#{abcs["test"]["username"]}" -f db/#{RAILS_ENV}_structure.sql #{abcs["test"]["database"]}`
- when "sqlite", "sqlite3"
- `#{abcs[RAILS_ENV]["adapter"]} #{abcs["test"]["dbfile"]} < db/#{RAILS_ENV}_structure.sql`
- when "sqlserver"
- `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
- else
- raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
- end
-end
-
-desc "Dump the database structure to a SQL file"
-task :db_structure_dump => :environment do
- abcs = ActiveRecord::Base.configurations
- case abcs[RAILS_ENV]["adapter"]
- when "mysql"
- ActiveRecord::Base.establish_connection(abcs[RAILS_ENV])
- File.open("db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
- when "postgresql"
- ENV['PGHOST'] = abcs[RAILS_ENV]["host"] if abcs[RAILS_ENV]["host"]
- ENV['PGPORT'] = abcs[RAILS_ENV]["port"].to_s if abcs[RAILS_ENV]["port"]
- ENV['PGPASSWORD'] = abcs[RAILS_ENV]["password"].to_s if abcs[RAILS_ENV]["password"]
- `pg_dump -U "#{abcs[RAILS_ENV]["username"]}" -s -x -O -f db/#{RAILS_ENV}_structure.sql #{abcs[RAILS_ENV]["database"]}`
- when "sqlite", "sqlite3"
- `#{abcs[RAILS_ENV]["adapter"]} #{abcs[RAILS_ENV]["dbfile"]} .schema > db/#{RAILS_ENV}_structure.sql`
- when "sqlserver"
- `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /f db\\#{RAILS_ENV}_structure.sql /q /A /r`
- `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /F db\ /q /A /r`
- else
- raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
- end
-end
-
-desc "Empty the test database"
-task :purge_test_database => :environment do
- abcs = ActiveRecord::Base.configurations
- case abcs["test"]["adapter"]
- when "mysql"
- ActiveRecord::Base.establish_connection(:test)
- ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"])
- when "postgresql"
- ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
- ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
- ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
- `dropdb -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
- `createdb -T template0 -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
- when "sqlite","sqlite3"
- File.delete(abcs["test"]["dbfile"]) if File.exist?(abcs["test"]["dbfile"])
- when "sqlserver"
- dropfkscript = "#{abcs["test"]["host"]}.#{abcs["test"]["database"]}.DP1".gsub(/\\/,'-')
- `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{dropfkscript}`
- `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
- else
- raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
- end
-end
-
-desc "Clears all *.log files in log/"
-task :clear_logs => :environment do
- FileList["log/*.log"].each do |log_file|
- f = File.open(log_file, "w")
- f.close
- end
-end
-
-desc "Migrate the database according to the migrate scripts in db/migrate (only supported on PG/MySQL). A specific version can be targetted with VERSION=x"
-task :migrate => :environment do
- ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/db/migrate/', ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
-end
\ No newline at end of file
diff --git a/app/models/page_observer.rb b/app/models/page_observer.rb
new file mode 100644
index 00000000..2ff58b64
--- /dev/null
+++ b/app/models/page_observer.rb
@@ -0,0 +1,15 @@
+# This class maintains the state of wiki references for newly created or newly deleted pages
+class PageObserver < ActiveRecord::Observer
+
+ def after_create(page)
+ WikiReference.update_all("link_type = '#{WikiReference::LINKED_PAGE}'",
+ ['referenced_page_name = ?', page.name])
+ end
+
+ def before_destroy(page)
+ WikiReference.delete_all ['page_id = ?', page.id]
+ WikiReference.update_all("link_type = '#{WikiReference::WANTED_PAGE}'",
+ ['referenced_page_name = ?', page.name])
+ end
+
+end
\ No newline at end of file
diff --git a/app/models/wiki_reference.rb b/app/models/wiki_reference.rb
new file mode 100644
index 00000000..074096bd
--- /dev/null
+++ b/app/models/wiki_reference.rb
@@ -0,0 +1,50 @@
+class WikiReference < ActiveRecord::Base
+
+ LINKED_PAGE = 'L'
+ WANTED_PAGE = 'W'
+ INCLUDED_PAGE = 'I'
+
+ belongs_to :page
+ validates_inclusion_of :link_type, :in => [LINKED_PAGE, WANTED_PAGE, INCLUDED_PAGE]
+
+ def self.link_type(web, page_name)
+ web.has_page?(page_name) ? LINKED_PAGE : WANTED_PAGE
+ end
+
+ def self.pages_that_reference(page_name)
+ query = 'SELECT name FROM pages JOIN wiki_references ON pages.id = wiki_references.page_id ' +
+ 'WHERE wiki_references.referenced_page_name = ?'
+ names = connection.select_all(sanitize_sql([query, page_name])).map { |row| row['name'] }
+ end
+
+ def self.pages_that_link_to(page_name)
+ query = 'SELECT name FROM pages JOIN wiki_references ON pages.id = wiki_references.page_id ' +
+ 'WHERE wiki_references.referenced_page_name = ? ' +
+ "AND wiki_references.link_type in ('#{LINKED_PAGE}', '#{WANTED_PAGE}')"
+ names = connection.select_all(sanitize_sql([query, page_name])).map { |row| row['name'] }
+ end
+
+ def self.pages_that_include(page_name)
+ query = 'SELECT name FROM pages JOIN wiki_references ON pages.id = wiki_references.page_id ' +
+ 'WHERE wiki_references.referenced_page_name = ? ' +
+ "AND wiki_references.link_type = '#{INCLUDED_PAGE}'"
+ names = connection.select_all(sanitize_sql([query, page_name])).map { |row| row['name'] }
+ end
+
+ def wiki_link?
+ linked_page? or wanted_page?
+ end
+
+ def linked_page?
+ link_type == LINKED_PAGE
+ end
+
+ def wanted_page?
+ link_type == WANTED_PAGE
+ end
+
+ def included_page?
+ link_type == INCLUDED_PAGE
+ end
+
+end
diff --git a/db/wiki_references.erbsql b/db/wiki_references.erbsql
new file mode 100644
index 00000000..e4485b0c
--- /dev/null
+++ b/db/wiki_references.erbsql
@@ -0,0 +1,9 @@
+CREATE TABLE wiki_references (
+ id <%= @pk %>,
+ created_at <%= @datetime %> NOT NULL,
+ updated_at <%= @datetime %> NOT NULL,
+
+ page_id INTEGER NOT NULL,
+ referenced_page_name VARCHAR NOT NULL,
+ link_type CHAR(1) NOT NULL
+) <%= create_options %>;
\ No newline at end of file
diff --git a/lib/page_renderer.rb b/lib/page_renderer.rb
index 61428bd2..b4a3877b 100644
--- a/lib/page_renderer.rb
+++ b/lib/page_renderer.rb
@@ -89,8 +89,9 @@ class PageRenderer
def render(options = {})
result = WikiContent.new(@revision, @@url_generator, options).render!
WikiReference.delete_all ['page_id = ?', @revision.page_id]
- @revision.page.wiki_references.delete
-
+
+ references = @revision.page.wiki_references
+
wiki_word_chunks = result.find_chunks(WikiChunk::WikiLink)
wiki_words = wiki_word_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
@@ -101,10 +102,14 @@ class PageRenderer
else
link_type = WikiReference.link_type(@revision.page.web, referenced_page_name)
end
- @revision.page.wiki_references.create({
- :referenced_page_name => referenced_page_name,
- :link_type => link_type
- })
+ references.create :referenced_page_name => referenced_page_name, :link_type => link_type
+ end
+
+ include_chunks = result.find_chunks(Include)
+ includes = include_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
+ includes.each do |included_page_name|
+ references.create :referenced_page_name => included_page_name,
+ :link_type => WikiReference::INCLUDED_PAGE
end
result
end
diff --git a/script/reset_references b/script/reset_references
new file mode 100644
index 00000000..0e21b0c9
--- /dev/null
+++ b/script/reset_references
@@ -0,0 +1,25 @@
+ENV['RAILS_ENV'] = ARGV.first || 'development'
+
+$stderr.puts "Loading Rails for #{ENV['RAILS_ENV']} environment..."
+require File.dirname(__FILE__) + '/../config/environment'
+
+class StubUrlGenerator
+ def make_link(*args)
+ 'StubLink'
+ end
+end
+
+PageRenderer.setup_url_generator(StubUrlGenerator.new)
+WikiReference.delete_all
+
+Web.find_all.each do |web|
+ web.pages.find(:all, :order => 'name').each do |page|
+ $stderr.puts "Processing page '#{page.name}'"
+ begin
+ PageRenderer.new(page.current_revision).display_content
+ rescue => e
+ puts e
+ puts e.backtrace
+ end
+ end
+end
\ No newline at end of file
diff --git a/test/fixtures/wiki_references.yml b/test/fixtures/wiki_references.yml
new file mode 100644
index 00000000..136f6aaa
--- /dev/null
+++ b/test/fixtures/wiki_references.yml
@@ -0,0 +1,95 @@
+my_way_1:
+ id: 1
+ page_id: 2
+ referenced_page_name: MyWay
+ link_type: L
+ created_at: <%= Time.now %>
+ updated_at: <%= Time.now %>
+
+smart_engine_1:
+ id: 2
+ page_id: 3
+ referenced_page_name: SmartEngine
+ link_type: L
+ created_at: <%= Time.now %>
+ updated_at: <%= Time.now %>
+
+that_way_1:
+ id: 3
+ page_id: 4
+ referenced_page_name: ThatWay
+ link_type: L
+ created_at: <%= Time.now %>
+ updated_at: <%= Time.now %>
+
+home_page_1:
+ id: 4
+ page_id: 1
+ referenced_page_name: HisWay
+ link_type: W
+ created_at: <%= Time.now %>
+ updated_at: <%= Time.now %>
+
+home_page_2:
+ id: 5
+ page_id: 1
+ referenced_page_name: MyWay
+ link_type: L
+ created_at: <%= Time.now %>
+ updated_at: <%= Time.now %>
+
+home_page_3:
+ id: 6
+ page_id: 1
+ referenced_page_name: ThatWay
+ link_type: L
+ created_at: <%= Time.now %>
+ updated_at: <%= Time.now %>
+
+home_page_4:
+ id: 7
+ page_id: 1
+ referenced_page_name: SmartEngine
+ link_type: L
+ created_at: <%= Time.now %>
+ updated_at: <%= Time.now %>
+
+first_page_1:
+ id: 8
+ page_id: 6
+ referenced_page_name: HisWay
+ link_type: W
+ created_at: <%= Time.now %>
+ updated_at: <%= Time.now %>
+
+first_page_2:
+ id: 9
+ page_id: 6
+ referenced_page_name: MyWay
+ link_type: L
+ created_at: <%= Time.now %>
+ updated_at: <%= Time.now %>
+
+first_page_3:
+ id: 10
+ page_id: 6
+ referenced_page_name: ThatWay
+ link_type: L
+ created_at: <%= Time.now %>
+ updated_at: <%= Time.now %>
+
+first_page_4:
+ id: 11
+ page_id: 6
+ referenced_page_name: OverThere
+ link_type: W
+ created_at: <%= Time.now %>
+ updated_at: <%= Time.now %>
+
+first_page_5:
+ id: 12
+ page_id: 6
+ referenced_page_name: SmartEngine
+ link_type: L
+ created_at: <%= Time.now %>
+ updated_at: <%= Time.now %>
diff --git a/test/unit/page_renderer_test.rb b/test/unit/page_renderer_test.rb
index 32c172db..1288ea85 100644
--- a/test/unit/page_renderer_test.rb
+++ b/test/unit/page_renderer_test.rb
@@ -326,8 +326,7 @@ class PageRendererTest < Test::Unit::TestCase
end
- # Tests for the caching of wiki references and categories
- def test_references_creation
+ def test_references_creation_links
new_page = @web.add_page('NewPage', 'HomePage NewPage',
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', test_renderer)
@@ -339,6 +338,16 @@ class PageRendererTest < Test::Unit::TestCase
assert_equal WikiReference::LINKED_PAGE, references[1].link_type
end
+ def test_references_creation_includes
+ new_page = @web.add_page('NewPage', '[[!include IncludedPage]]',
+ Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', test_renderer)
+
+ references = new_page.wiki_references(true)
+ assert_equal 1, references.size
+ assert_equal 'IncludedPage', references[0].referenced_page_name
+ assert_equal WikiReference::INCLUDED_PAGE, references[0].link_type
+ end
+
private
def add_sample_pages
From 303622341bd56bc4a5fd36a837ffe638715dcaf3 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Sun, 11 Sep 2005 14:04:52 +0000
Subject: [PATCH 54/84] Ignoring the cached stuff in public
From c4f593151eae8a3bb24eefafc865b15c6d5176bd Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Sun, 11 Sep 2005 16:49:08 +0000
Subject: [PATCH 55/84] [FIXES BUILD] Fixed categories behavior and added id
generation in import_storage. Something is still wrong with orphaned pages
though
---
app/controllers/wiki_controller.rb | 17 ++-----
app/models/page.rb | 6 +--
app/models/page_observer.rb | 4 +-
app/models/page_set.rb | 4 +-
app/models/web.rb | 4 ++
app/models/wiki_reference.rb | 24 ++++++++--
db/wiki_references.erbsql | 2 +-
lib/page_renderer.rb | 15 ++++--
script/import_storage | 74 ++++++++++++++++++++++--------
test/fixtures/wiki_references.yml | 41 ++++++++++++-----
test/unit/page_renderer_test.rb | 16 +++++--
test/unit/page_test.rb | 8 ++--
12 files changed, 149 insertions(+), 66 deletions(-)
diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb
index be93de83..62905dcf 100644
--- a/app/controllers/wiki_controller.rb
+++ b/app/controllers/wiki_controller.rb
@@ -289,20 +289,13 @@ class WikiController < ApplicationController
def parse_category
@category = @params['category']
- @categories = []
- @pages_in_category = @web.select do |page|
- # FIXME: was PageRenderer.new(page.revisions.last).display_content.find_chunks(Category),
- # heinously slow
- page_categories = []
- page_categories = page_categories.map { |cat| cat.list }.flatten
- page_categories.each {|c| @categories << c unless @categories.include? c }
- page_categories.include?(@category)
- end
- @categories.sort!
- if (@pages_in_category.empty?)
- @pages_in_category = PageSet.new(@web).by_name
+ @categories = WikiReference.list_categories.sort
+ page_names_in_category = WikiReference.pages_in_category(@category)
+ if (page_names_in_category.empty?)
+ @pages_in_category = @web.select_all.by_name
@set_name = 'the web'
else
+ @pages_in_category = @web.select { |page| page_names_in_category.include?(page.name) }.by_name
@set_name = "category '#{@category}'"
end
end
diff --git a/app/models/page.rb b/app/models/page.rb
index 715ac6ce..a44b5558 100644
--- a/app/models/page.rb
+++ b/app/models/page.rb
@@ -1,7 +1,7 @@
class Page < ActiveRecord::Base
belongs_to :web
has_many :revisions, :order => 'id'
- has_many :wiki_references, :order => 'referenced_page_name'
+ has_many :wiki_references, :order => 'referenced_name'
has_one :current_revision, :class_name => 'Revision', :order => 'id DESC'
def revise(content, time, author, renderer)
@@ -15,7 +15,7 @@ class Page < ActiveRecord::Base
# Try to render content to make sure that markup engine can take it,
renderer.revision = Revision.new(
- :page => self, :content => content, :author => author, :revised_at => time)
+ :page => self, :content => content, :author => author, :revised_at => time)
renderer.display_content
# A user may change a page, look at it and make some more changes - several times.
@@ -25,7 +25,7 @@ class Page < ActiveRecord::Base
if (revisions_size > 0) && continous_revision?(time, author)
current_revision.update_attributes(:content => content, :revised_at => time)
else
- Revision.create(:page => self, :content => content, :author => author, :revised_at => time)
+ revisions.create(:content => content, :author => author, :revised_at => time)
end
save
self
diff --git a/app/models/page_observer.rb b/app/models/page_observer.rb
index 2ff58b64..13211a14 100644
--- a/app/models/page_observer.rb
+++ b/app/models/page_observer.rb
@@ -3,13 +3,13 @@ class PageObserver < ActiveRecord::Observer
def after_create(page)
WikiReference.update_all("link_type = '#{WikiReference::LINKED_PAGE}'",
- ['referenced_page_name = ?', page.name])
+ ['referenced_name = ?', page.name])
end
def before_destroy(page)
WikiReference.delete_all ['page_id = ?', page.id]
WikiReference.update_all("link_type = '#{WikiReference::WANTED_PAGE}'",
- ['referenced_page_name = ?', page.name])
+ ['referenced_name = ?', page.name])
end
end
\ No newline at end of file
diff --git a/app/models/page_set.rb b/app/models/page_set.rb
index 6a9b2700..873e4c49 100644
--- a/app/models/page_set.rb
+++ b/app/models/page_set.rb
@@ -82,7 +82,9 @@ class PageSet < Array
def wiki_words
self.inject([]) { |wiki_words, page|
- wiki_words + page.wiki_references.map { |ref| ref.referenced_page_name }
+ wiki_words + page.wiki_references.
+ select { |ref| ref.link_type != WikiReference::CATEGORY }.
+ map { |ref| ref.referenced_name }
}.flatten.uniq
end
diff --git a/app/models/web.rb b/app/models/web.rb
index 62f88623..65a97832 100644
--- a/app/models/web.rb
+++ b/app/models/web.rb
@@ -56,6 +56,10 @@ class Web < ActiveRecord::Base
PageSet.new(self, pages, condition)
end
+ def select_all
+ PageSet.new(self, pages, nil)
+ end
+
private
# Returns an array of all the wiki words in any current revision
diff --git a/app/models/wiki_reference.rb b/app/models/wiki_reference.rb
index 074096bd..6ebe1d55 100644
--- a/app/models/wiki_reference.rb
+++ b/app/models/wiki_reference.rb
@@ -3,9 +3,12 @@ class WikiReference < ActiveRecord::Base
LINKED_PAGE = 'L'
WANTED_PAGE = 'W'
INCLUDED_PAGE = 'I'
+ CATEGORY = 'C'
belongs_to :page
- validates_inclusion_of :link_type, :in => [LINKED_PAGE, WANTED_PAGE, INCLUDED_PAGE]
+ validates_inclusion_of :link_type, :in => [LINKED_PAGE, WANTED_PAGE, INCLUDED_PAGE, CATEGORY]
+
+ # FIXME all finders below MUST restrict their results to pages belonging to a particular web
def self.link_type(web, page_name)
web.has_page?(page_name) ? LINKED_PAGE : WANTED_PAGE
@@ -13,24 +16,37 @@ class WikiReference < ActiveRecord::Base
def self.pages_that_reference(page_name)
query = 'SELECT name FROM pages JOIN wiki_references ON pages.id = wiki_references.page_id ' +
- 'WHERE wiki_references.referenced_page_name = ?'
+ 'WHERE wiki_references.referenced_name = ?' +
+ "AND wiki_references.link_type in ('#{LINKED_PAGE}', '#{WANTED_PAGE}', '#{INCLUDED_PAGE}')"
names = connection.select_all(sanitize_sql([query, page_name])).map { |row| row['name'] }
end
def self.pages_that_link_to(page_name)
query = 'SELECT name FROM pages JOIN wiki_references ON pages.id = wiki_references.page_id ' +
- 'WHERE wiki_references.referenced_page_name = ? ' +
+ 'WHERE wiki_references.referenced_name = ? ' +
"AND wiki_references.link_type in ('#{LINKED_PAGE}', '#{WANTED_PAGE}')"
names = connection.select_all(sanitize_sql([query, page_name])).map { |row| row['name'] }
end
def self.pages_that_include(page_name)
query = 'SELECT name FROM pages JOIN wiki_references ON pages.id = wiki_references.page_id ' +
- 'WHERE wiki_references.referenced_page_name = ? ' +
+ 'WHERE wiki_references.referenced_name = ? ' +
"AND wiki_references.link_type = '#{INCLUDED_PAGE}'"
names = connection.select_all(sanitize_sql([query, page_name])).map { |row| row['name'] }
end
+ def self.pages_in_category(category)
+ query = 'SELECT name FROM pages JOIN wiki_references ON pages.id = wiki_references.page_id ' +
+ 'WHERE wiki_references.referenced_name = ? ' +
+ "AND wiki_references.link_type = '#{CATEGORY}'"
+ names = connection.select_all(sanitize_sql([query, category])).map { |row| row['name'] }
+ end
+
+ def self.list_categories
+ query = "SELECT DISTINCT referenced_name FROM wiki_references WHERE link_type = '#{CATEGORY}'"
+ connection.select_all(query).map { |row| row['referenced_name'] }
+ end
+
def wiki_link?
linked_page? or wanted_page?
end
diff --git a/db/wiki_references.erbsql b/db/wiki_references.erbsql
index e4485b0c..5dbe72d6 100644
--- a/db/wiki_references.erbsql
+++ b/db/wiki_references.erbsql
@@ -4,6 +4,6 @@ CREATE TABLE wiki_references (
updated_at <%= @datetime %> NOT NULL,
page_id INTEGER NOT NULL,
- referenced_page_name VARCHAR NOT NULL,
+ referenced_name VARCHAR NOT NULL,
link_type CHAR(1) NOT NULL
) <%= create_options %>;
\ No newline at end of file
diff --git a/lib/page_renderer.rb b/lib/page_renderer.rb
index b4a3877b..07b6a3fb 100644
--- a/lib/page_renderer.rb
+++ b/lib/page_renderer.rb
@@ -95,22 +95,27 @@ class PageRenderer
wiki_word_chunks = result.find_chunks(WikiChunk::WikiLink)
wiki_words = wiki_word_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
- wiki_words.each do |referenced_page_name|
+ wiki_words.each do |referenced_name|
# Links to self are always considered linked
- if referenced_page_name == @revision.page.name
+ if referenced_name == @revision.page.name
link_type = WikiReference::LINKED_PAGE
else
- link_type = WikiReference.link_type(@revision.page.web, referenced_page_name)
+ link_type = WikiReference.link_type(@revision.page.web, referenced_name)
end
- references.create :referenced_page_name => referenced_page_name, :link_type => link_type
+ references.create :referenced_name => referenced_name, :link_type => link_type
end
include_chunks = result.find_chunks(Include)
includes = include_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
includes.each do |included_page_name|
- references.create :referenced_page_name => included_page_name,
+ references.create :referenced_name => included_page_name,
:link_type => WikiReference::INCLUDED_PAGE
end
+
+ categories = result.find_chunks(Category).map { |cat| cat.list }.flatten
+ categories.each do |category|
+ references.create :referenced_name => category, :link_type => WikiReference::CATEGORY
+ end
result
end
end
diff --git a/script/import_storage b/script/import_storage
index c257004f..3e4ef512 100755
--- a/script/import_storage
+++ b/script/import_storage
@@ -76,7 +76,7 @@ expected_page_rb_path = File.join(OPTIONS[:instiki], 'app/models/page.rb')
raise "Instiki installation not found in #{OPTIONS[:instiki]}" unless File.file?(expected_page_rb_path)
expected_snapshot_pattern = File.join(OPTIONS[:storage], '*.snapshot')
-raise "No snapshots found in OPTIONS[:storage]" if Dir[expected_snapshot_pattern].empty?
+raise "No snapshots found in #{expected_snapshot_pattern}" if Dir[expected_snapshot_pattern].empty?
INSTIKI_ROOT = File.expand_path(OPTIONS[:instiki])
@@ -109,31 +109,61 @@ class Time
end
def sql_insert(table, hash)
- output = "INSERT INTO #{table} ("
- output << hash.keys.join(", ")
+ columns = hash.keys
- output << ") VALUES ('"
- output << hash.values.map do |v|
- case OPTIONS[:database]
- when 'mysql', 'postgres'
- v.to_s.gsub("'", "\\\\'")
- when 'sqlite'
- v.to_s.gsub("'", "''")
- else
- raise "Unsupported database option #{OPTIONS[:database]}"
+ values = columns.map { |column| hash[column] }
+ values = values.map do |val|
+ if val.nil?
+ 'NULL'
+ else
+ case OPTIONS[:database]
+ when 'mysql', 'postgres'
+ escaped_value = val.to_s.gsub("'", "\\\\'")
+ when 'sqlite'
+ escaped_value = val.to_s.gsub("'", "''")
+ else
+ raise "Unsupported database option #{OPTIONS[:database]}"
+ end
+ "'#{escaped_value}'"
end
- end.join("', '")
- output << "');"
+ end
+
+ output = "INSERT INTO #{table} ("
+ output << columns.join(", ")
+
+ output << ") VALUES ("
+ output << values.join(", ")
+ output << ");"
output
end
+def delete_all(outfile)
+ %w(wiki_references revisions pages system webs).each { |table| outfile.puts "DELETE FROM #{table};" }
+end
+
+def next_id(key)
+ $ids ||= {}
+ if $ids[key].nil?
+ $ids[key] = 1
+ else
+ $ids[key] = $ids[key] + 1
+ end
+ $ids[key]
+end
+
+def current_id(key)
+ $ids[key] or raise "No curent ID for #{key.inspect}"
+end
+
WikiService.storage_path = OPTIONS[:storage]
wiki = WikiService.instance
File.open(OPTIONS[:outfile], 'w') { |outfile|
+ delete_all(outfile)
+
wiki.webs.each_pair do |web_name, web|
outfile.puts sql_insert(:webs, {
- :id => web.object_id,
+ :id => next_id(:web),
:name => web.name,
:address => web.address,
:password => web.password,
@@ -152,9 +182,12 @@ File.open(OPTIONS[:outfile], 'w') { |outfile|
puts "Web #{web_name} has #{web.pages.keys.size} pages"
web.pages.each_pair do |page_name, page|
+
+ outfile.puts "BEGIN TRANSACTION;"
+
outfile.puts sql_insert(:pages, {
- :id => page.object_id,
- :web_id => web.object_id,
+ :id => next_id(:page),
+ :web_id => current_id(:web),
:locked_by => page.locked_by,
:name => page.name,
:created_at => page.revisions.first.created_at.ansi,
@@ -165,8 +198,8 @@ File.open(OPTIONS[:outfile], 'w') { |outfile|
page.revisions.each_with_index do |rev, i|
outfile.puts sql_insert(:revisions, {
- :id => rev.object_id,
- :page_id => page.object_id,
+ :id => next_id(:revision),
+ :page_id => current_id(:page),
:content => rev.content,
:author => rev.author.to_s,
:ip => (rev.author.is_a?(Author) ? rev.author.ip : 'N/A'),
@@ -176,6 +209,9 @@ File.open(OPTIONS[:outfile], 'w') { |outfile|
})
puts " Revision #{i} created at #{rev.created_at.ansi}"
end
+
+ outfile.puts "COMMIT;"
+
end
end
}
diff --git a/test/fixtures/wiki_references.yml b/test/fixtures/wiki_references.yml
index 136f6aaa..5d681261 100644
--- a/test/fixtures/wiki_references.yml
+++ b/test/fixtures/wiki_references.yml
@@ -1,7 +1,7 @@
my_way_1:
id: 1
page_id: 2
- referenced_page_name: MyWay
+ referenced_name: MyWay
link_type: L
created_at: <%= Time.now %>
updated_at: <%= Time.now %>
@@ -9,7 +9,7 @@ my_way_1:
smart_engine_1:
id: 2
page_id: 3
- referenced_page_name: SmartEngine
+ referenced_name: SmartEngine
link_type: L
created_at: <%= Time.now %>
updated_at: <%= Time.now %>
@@ -17,7 +17,7 @@ smart_engine_1:
that_way_1:
id: 3
page_id: 4
- referenced_page_name: ThatWay
+ referenced_name: ThatWay
link_type: L
created_at: <%= Time.now %>
updated_at: <%= Time.now %>
@@ -25,7 +25,7 @@ that_way_1:
home_page_1:
id: 4
page_id: 1
- referenced_page_name: HisWay
+ referenced_name: HisWay
link_type: W
created_at: <%= Time.now %>
updated_at: <%= Time.now %>
@@ -33,7 +33,7 @@ home_page_1:
home_page_2:
id: 5
page_id: 1
- referenced_page_name: MyWay
+ referenced_name: MyWay
link_type: L
created_at: <%= Time.now %>
updated_at: <%= Time.now %>
@@ -41,7 +41,7 @@ home_page_2:
home_page_3:
id: 6
page_id: 1
- referenced_page_name: ThatWay
+ referenced_name: ThatWay
link_type: L
created_at: <%= Time.now %>
updated_at: <%= Time.now %>
@@ -49,7 +49,7 @@ home_page_3:
home_page_4:
id: 7
page_id: 1
- referenced_page_name: SmartEngine
+ referenced_name: SmartEngine
link_type: L
created_at: <%= Time.now %>
updated_at: <%= Time.now %>
@@ -57,7 +57,7 @@ home_page_4:
first_page_1:
id: 8
page_id: 6
- referenced_page_name: HisWay
+ referenced_name: HisWay
link_type: W
created_at: <%= Time.now %>
updated_at: <%= Time.now %>
@@ -65,7 +65,7 @@ first_page_1:
first_page_2:
id: 9
page_id: 6
- referenced_page_name: MyWay
+ referenced_name: MyWay
link_type: L
created_at: <%= Time.now %>
updated_at: <%= Time.now %>
@@ -73,7 +73,7 @@ first_page_2:
first_page_3:
id: 10
page_id: 6
- referenced_page_name: ThatWay
+ referenced_name: ThatWay
link_type: L
created_at: <%= Time.now %>
updated_at: <%= Time.now %>
@@ -81,7 +81,7 @@ first_page_3:
first_page_4:
id: 11
page_id: 6
- referenced_page_name: OverThere
+ referenced_name: OverThere
link_type: W
created_at: <%= Time.now %>
updated_at: <%= Time.now %>
@@ -89,7 +89,24 @@ first_page_4:
first_page_5:
id: 12
page_id: 6
- referenced_page_name: SmartEngine
+ referenced_name: SmartEngine
link_type: L
created_at: <%= Time.now %>
updated_at: <%= Time.now %>
+
+oak_1:
+ id: 13
+ page_id: 7
+ referenced_name: trees
+ link_type: C
+ created_at: <%= Time.now %>
+ updated_at: <%= Time.now %>
+
+elephant_1:
+ id: 14
+ page_id: 8
+ referenced_name: animals
+ link_type: C
+ created_at: <%= Time.now %>
+ updated_at: <%= Time.now %>
+
\ No newline at end of file
diff --git a/test/unit/page_renderer_test.rb b/test/unit/page_renderer_test.rb
index 1288ea85..50ce9e6a 100644
--- a/test/unit/page_renderer_test.rb
+++ b/test/unit/page_renderer_test.rb
@@ -332,9 +332,9 @@ class PageRendererTest < Test::Unit::TestCase
references = new_page.wiki_references(true)
assert_equal 2, references.size
- assert_equal 'HomePage', references[0].referenced_page_name
+ assert_equal 'HomePage', references[0].referenced_name
assert_equal WikiReference::LINKED_PAGE, references[0].link_type
- assert_equal 'NewPage', references[1].referenced_page_name
+ assert_equal 'NewPage', references[1].referenced_name
assert_equal WikiReference::LINKED_PAGE, references[1].link_type
end
@@ -344,10 +344,20 @@ class PageRendererTest < Test::Unit::TestCase
references = new_page.wiki_references(true)
assert_equal 1, references.size
- assert_equal 'IncludedPage', references[0].referenced_page_name
+ assert_equal 'IncludedPage', references[0].referenced_name
assert_equal WikiReference::INCLUDED_PAGE, references[0].link_type
end
+ def test_references_creation_categories
+ new_page = @web.add_page('NewPage', "Foo\ncategory: NewPageCategory",
+ Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', test_renderer)
+
+ references = new_page.wiki_references(true)
+ assert_equal 1, references.size
+ assert_equal 'NewPageCategory', references[0].referenced_name
+ assert_equal WikiReference::CATEGORY, references[0].link_type
+ end
+
private
def add_sample_pages
diff --git a/test/unit/page_test.rb b/test/unit/page_test.rb
index e466b926..f9527430 100644
--- a/test/unit/page_test.rb
+++ b/test/unit/page_test.rb
@@ -93,9 +93,9 @@ class PageTest < Test::Unit::TestCase
references = new_page.wiki_references(true)
assert_equal 2, references.size
- assert_equal 'WantedPage', references[0].referenced_page_name
+ assert_equal 'WantedPage', references[0].referenced_name
assert_equal WikiReference::WANTED_PAGE, references[0].link_type
- assert_equal 'WantedPage2', references[1].referenced_page_name
+ assert_equal 'WantedPage2', references[1].referenced_name
assert_equal WikiReference::WANTED_PAGE, references[1].link_type
wanted_page = Page.new(:web => web, :name => 'WantedPage')
@@ -105,9 +105,9 @@ class PageTest < Test::Unit::TestCase
# reference NewPage -> WantedPage2 should remain the same
references = new_page.wiki_references(true)
assert_equal 2, references.size
- assert_equal 'WantedPage', references[0].referenced_page_name
+ assert_equal 'WantedPage', references[0].referenced_name
assert_equal WikiReference::LINKED_PAGE, references[0].link_type
- assert_equal 'WantedPage2', references[1].referenced_page_name
+ assert_equal 'WantedPage2', references[1].referenced_name
assert_equal WikiReference::WANTED_PAGE, references[1].link_type
end
From cc99790a4a1a9c953d82cc72fbf410b42d8b103f Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Sun, 11 Sep 2005 18:02:56 +0000
Subject: [PATCH 56/84] Caching and sweeping pages. RSS feeds behave funny
---
app/controllers/revision_sweeper.rb | 24 ++++++++++++++++++++++++
app/controllers/wiki_controller.rb | 6 ++++--
2 files changed, 28 insertions(+), 2 deletions(-)
create mode 100644 app/controllers/revision_sweeper.rb
diff --git a/app/controllers/revision_sweeper.rb b/app/controllers/revision_sweeper.rb
new file mode 100644
index 00000000..21421c7b
--- /dev/null
+++ b/app/controllers/revision_sweeper.rb
@@ -0,0 +1,24 @@
+class RevisionSweeper < ActionController::Caching::Sweeper
+ observe Revision, Page
+
+ def after_save(record)
+ if record.is_a?(Revision)
+ expire_caches(record.page)
+ end
+ end
+
+ def after_delete(record)
+ if record.is_a?(Page)
+ expire_caches(record)
+ end
+ end
+
+ private
+
+ def expire_caches(page)
+ expire_page :controller => 'wiki', :web => page.web.address,
+ :action => %w(show published), :id => page.name
+ expire_page :controller => 'wiki', :web => page.web.address,
+ :action => %w(authors recently_revised list rss_with_content rss_with_headlines)
+ end
+end
diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb
index 62905dcf..bd66c960 100644
--- a/app/controllers/wiki_controller.rb
+++ b/app/controllers/wiki_controller.rb
@@ -6,8 +6,9 @@ require 'zip/zip'
class WikiController < ApplicationController
# TODO implement cache sweeping
- caches_page :show, :published
-
+ caches_page :show, :published, :authors, :recently_revised, :list, :rss_with_content, :rss_with_headlines
+ cache_sweeper :revision_sweeper
+
layout 'default', :except => [:rss_feed, :rss_with_content, :rss_with_headlines, :tex, :export_tex, :export_html]
def index
@@ -194,6 +195,7 @@ class WikiController < ApplicationController
redirect_to_page @page_name
rescue => e
flash[:error] = e
+ logger.error e
flash[:content] = @params['content']
if @page
@page.unlock
From 4c14f0710021325163aeb3d20aa91dcaf9c79aab Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Mon, 12 Sep 2005 01:12:00 +0000
Subject: [PATCH 57/84] Fixed caching of RSS feeds; changed from caches_page to
caches_action to make authentication and other filters work
---
app/controllers/application.rb | 10 +++++++---
app/controllers/revision_sweeper.rb | 9 ++++++---
app/controllers/wiki_controller.rb | 7 +++----
app/views/wiki/rss_feed.rhtml | 22 ----------------------
app/views/wiki/rss_feed.rxml | 21 +++++++++++++++++++++
test/functional/wiki_controller_test.rb | 2 +-
6 files changed, 38 insertions(+), 33 deletions(-)
delete mode 100644 app/views/wiki/rss_feed.rhtml
create mode 100644 app/views/wiki/rss_feed.rxml
diff --git a/app/controllers/application.rb b/app/controllers/application.rb
index 05fb89ce..a4133850 100644
--- a/app/controllers/application.rb
+++ b/app/controllers/application.rb
@@ -2,7 +2,7 @@
# Likewise will all the methods added be available for all controllers.
class ApplicationController < ActionController::Base
- before_filter :set_utf8_http_header, :connect_to_model, :setup_url_generator
+ before_filter :connect_to_model, :setup_url_generator, :set_content_type_header
after_filter :remember_location, :teardown_url_generator
observer :page_observer
@@ -144,8 +144,12 @@ class ApplicationController < ActionController::Base
end
end
- def set_utf8_http_header
- @response.headers['Content-Type'] = 'text/html; charset=UTF-8'
+ def set_content_type_header
+ if %w(rss_with_content rss_with_headlines).include?(action_name)
+ @response.headers['Content-Type'] = 'text/xml; charset=UTF-8'
+ else
+ @response.headers['Content-Type'] = 'text/html; charset=UTF-8'
+ end
end
def setup_url_generator
diff --git a/app/controllers/revision_sweeper.rb b/app/controllers/revision_sweeper.rb
index 21421c7b..1ab4676b 100644
--- a/app/controllers/revision_sweeper.rb
+++ b/app/controllers/revision_sweeper.rb
@@ -16,9 +16,12 @@ class RevisionSweeper < ActionController::Caching::Sweeper
private
def expire_caches(page)
- expire_page :controller => 'wiki', :web => page.web.address,
+ web = page.web
+ expire_action :controller => 'wiki', :web => web.address,
:action => %w(show published), :id => page.name
- expire_page :controller => 'wiki', :web => page.web.address,
- :action => %w(authors recently_revised list rss_with_content rss_with_headlines)
+ expire_action :controller => 'wiki', :web => web.address,
+ :action => %w(authors recently_revised list)
+ expire_fragment :controller => 'wiki', :web => web.address,
+ :action => %w(rss_with_headlines rss_with_content)
end
end
diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb
index bd66c960..fdd83d21 100644
--- a/app/controllers/wiki_controller.rb
+++ b/app/controllers/wiki_controller.rb
@@ -6,7 +6,7 @@ require 'zip/zip'
class WikiController < ApplicationController
# TODO implement cache sweeping
- caches_page :show, :published, :authors, :recently_revised, :list, :rss_with_content, :rss_with_headlines
+ caches_action :show, :published, :authors, :recently_revised, :list
cache_sweeper :revision_sweeper
layout 'default', :except => [:rss_feed, :rss_with_content, :rss_with_headlines, :tex, :export_tex, :export_html]
@@ -330,10 +330,9 @@ class WikiController < ApplicationController
end
@hide_description = hide_description
- @response.headers['Content-Type'] = 'text/xml'
@link_action = @web.password ? 'published' : 'show'
- render 'wiki/rss_feed'
+ render :action => 'rss_feed'
end
def render_tex_web
@@ -346,7 +345,7 @@ class WikiController < ApplicationController
def render_to_string(template_name, with_layout = false)
add_variables_to_assigns
self.assigns['content_for_layout'] = @template.render_file(template_name)
- if with_layout
+ if with_layout
@template.render_file('layouts/default')
else
self.assigns['content_for_layout']
diff --git a/app/views/wiki/rss_feed.rhtml b/app/views/wiki/rss_feed.rhtml
deleted file mode 100644
index 47815c49..00000000
--- a/app/views/wiki/rss_feed.rhtml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
- <%= @web.name %>
- <%= url_for :only_path => false, :web => @web_name, :action => @link_action, :id => 'HomePage' %>
- An Instiki wiki
- en-us
- 40
- <% for page in @pages_by_revision %>
-
- <%= h page.plain_name %>
- <% unless @hide_description %>
- <%= h rendered_content(page) %>
- <% end %>
- <%= page.revised_at.getgm.strftime "%a, %d %b %Y %H:%M:%S Z" %>
- <%= url_for :only_path => false, :web => @web_name, :action => @link_action, :id => page.name %>
- <%= url_for :only_path => false, :web => @web_name, :action => @link_action, :id => page.name %>
- <%= WikiWords.separate(page.author) %>
-
- <% end %>
-
-
diff --git a/app/views/wiki/rss_feed.rxml b/app/views/wiki/rss_feed.rxml
new file mode 100644
index 00000000..4b52f7d2
--- /dev/null
+++ b/app/views/wiki/rss_feed.rxml
@@ -0,0 +1,21 @@
+xml.rss('version' => '2.0') do
+ xml.channel do
+ xml.title(@web.name)
+ xml.link(url_for(:only_path => false, :web => @web_name, :action => @link_action, :id => 'HomePage'))
+ xml.description('An Instiki wiki')
+ xml.language('en-us')
+ xml.ttl('40')
+
+ for page in @pages_by_revision
+ xml.item do
+ xml.title(page.plain_name)
+ unless @hide_description
+ xml.description(rendered_content(page))
+ end
+ xml.pubDate(page.revised_at.getgm.strftime('%a, %d %b %Y %H:%M:%S Z'))
+ xml.guid(url_for(:only_path => false, :web => @web_name, :action => @link_action, :id => page.name))
+ xml.link(url_for(:only_path => false, :web => @web_name, :action => @link_action, :id => page.name))
+ end
+ end
+ end
+end
diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb
index 54c541b3..8be34cb4 100755
--- a/test/functional/wiki_controller_test.rb
+++ b/test/functional/wiki_controller_test.rb
@@ -485,7 +485,7 @@ class WikiControllerTest < Test::Unit::TestCase
end
def test_rss_title_with_ampersand
- # was ticket:143
+ # was ticket:143
@wiki.write_page('wiki1', 'Title&With&Ampersands',
'About spaces', 1.hour.ago, Author.new('NitPicker', '127.0.0.3'), test_renderer)
From 4a8d6eefe083c5d4bcd65604b0b6cc9b7cfb1da5 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Wed, 14 Sep 2005 02:01:20 +0000
Subject: [PATCH 58/84] Fixed chunk mask to handle negative object_id values
[Venkat]
---
lib/chunks/chunk.rb | 2 +-
lib/chunks/include.rb | 7 +++++--
rakefile.rb | 2 +-
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/lib/chunks/chunk.rb b/lib/chunks/chunk.rb
index ad0fb148..18de7d0c 100644
--- a/lib/chunks/chunk.rb
+++ b/lib/chunks/chunk.rb
@@ -28,7 +28,7 @@ module Chunk
# a regexp that matches all chunk_types masks
def Abstract::mask_re(chunk_types)
chunk_classes = chunk_types.map{|klass| klass.mask_string}.join("|")
- /chunk(\d+)(#{chunk_classes})chunk/
+ /chunk(-?\d+)(#{chunk_classes})chunk/
end
attr_reader :text, :unmask_text, :unmask_mode
diff --git a/lib/chunks/include.rb b/lib/chunks/include.rb
index 72c89b54..d58ff22c 100644
--- a/lib/chunks/include.rb
+++ b/lib/chunks/include.rb
@@ -30,8 +30,11 @@ class Include < WikiChunk::WikiReference
return "Recursive include detected; #{@page_name} --> #{@content.page_name} " +
"--> #{@page_name}\n"
else
- @content.merge_chunks(renderer.display_content)
- return renderer.display_content.pre_rendered
+require 'breakpoint'
+breakpoint
+ included_content = renderer.display_content
+ @content.merge_chunks(included_content)
+ return included_content.pre_rendered
end
else
return "Could not include #{@page_name}\n"
diff --git a/rakefile.rb b/rakefile.rb
index fb2dfd40..af9c997f 100755
--- a/rakefile.rb
+++ b/rakefile.rb
@@ -202,4 +202,4 @@ task :migrate => :environment do
end
task :ft => :test_functional
-task :ut => :test_unit
\ No newline at end of file
+task :ut => :test_units
\ No newline at end of file
From 79cf8a0ea12887fea43b36cd2ac76c7857e2b8e6 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Wed, 14 Sep 2005 02:02:00 +0000
Subject: [PATCH 59/84] Removing breakpoint from include.rb
---
lib/chunks/include.rb | 2 --
1 file changed, 2 deletions(-)
diff --git a/lib/chunks/include.rb b/lib/chunks/include.rb
index d58ff22c..dbd9d3dd 100644
--- a/lib/chunks/include.rb
+++ b/lib/chunks/include.rb
@@ -30,8 +30,6 @@ class Include < WikiChunk::WikiReference
return "Recursive include detected; #{@page_name} --> #{@content.page_name} " +
"--> #{@page_name}\n"
else
-require 'breakpoint'
-breakpoint
included_content = renderer.display_content
@content.merge_chunks(included_content)
return included_content.pre_rendered
From 1d44ce1c18369c32d600a7a45ec030d0739155b1 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Fri, 16 Sep 2005 04:27:07 +0000
Subject: [PATCH 60/84] Upgraded RedCloth to 3.0.4
---
CHANGELOG | 6 +
instiki.gemspec | 2 +-
script/import_storage | 2 +-
vendor/RedCloth-3.0.3/RedCloth.gemspec | 52 -
vendor/RedCloth-3.0.3/install.rb | 1032 -------------
.../bin/redcloth | 2 +-
.../doc/CHANGELOG | 11 +
.../doc/COPYING | 0
.../doc/README | 6 +-
.../doc/REFERENCE | 8 +-
.../doc/make.rb | 0
.../lib/redcloth.rb | 137 +-
.../run-tests.rb | 4 +-
vendor/RedCloth-3.0.4/setup.rb | 1376 +++++++++++++++++
.../tests/code.yml | 0
vendor/RedCloth-3.0.4/tests/hard_breaks.yml | 26 +
.../tests/images.yml | 0
.../tests/instiki.yml | 0
.../tests/links.yml | 0
.../tests/lists.yml | 0
.../tests/markdown.yml | 0
.../tests/poignant.yml | 0
.../tests/table.yml | 8 +-
.../tests/textism.yml | 9 +
24 files changed, 1521 insertions(+), 1160 deletions(-)
delete mode 100644 vendor/RedCloth-3.0.3/RedCloth.gemspec
delete mode 100644 vendor/RedCloth-3.0.3/install.rb
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/bin/redcloth (70%)
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/doc/CHANGELOG (92%)
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/doc/COPYING (100%)
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/doc/README (91%)
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/doc/REFERENCE (98%)
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/doc/make.rb (100%)
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/lib/redcloth.rb (94%)
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/run-tests.rb (83%)
create mode 100644 vendor/RedCloth-3.0.4/setup.rb
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/tests/code.yml (100%)
create mode 100644 vendor/RedCloth-3.0.4/tests/hard_breaks.yml
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/tests/images.yml (100%)
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/tests/instiki.yml (100%)
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/tests/links.yml (100%)
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/tests/lists.yml (100%)
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/tests/markdown.yml (100%)
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/tests/poignant.yml (100%)
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/tests/table.yml (95%)
rename vendor/{RedCloth-3.0.3 => RedCloth-3.0.4}/tests/textism.yml (97%)
diff --git a/CHANGELOG b/CHANGELOG
index 519da063..d093c887 100755
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,9 @@
+ * instiki-ar
+ SQL-based backend (ActiveRecord)
+ Upgrade to RedCloth 3.0.4
+ Replaced internal link generator with routing
+ Fixed --daemon option
+
* 0.10.2:
Upgraded to Rails 0.13.1
Fixed HTML export
diff --git a/instiki.gemspec b/instiki.gemspec
index c65ac414..caeee714 100755
--- a/instiki.gemspec
+++ b/instiki.gemspec
@@ -24,7 +24,7 @@ spec = Gem::Specification.new do |s|
s.has_rdoc = false
- s.add_dependency('RedCloth', '= 3.0.3')
+ s.add_dependency('RedCloth', '= 3.0.4')
s.add_dependency('rubyzip', '= 0.5.8')
s.add_dependency('rails', '= 0.13.1')
s.add_dependency('sqlite3-ruby', '= 1.1.0')
diff --git a/script/import_storage b/script/import_storage
index 3e4ef512..0f6d6b21 100755
--- a/script/import_storage
+++ b/script/import_storage
@@ -84,7 +84,7 @@ ADDITIONAL_LOAD_PATHS = %w(
app/models
lib
vendor/madeleine-0.7.1/lib
- vendor/RedCloth-3.0.3/lib
+ vendor/RedCloth-3.0.4/lib
vendor/rubyzip-0.5.8/lib
).map { |dir| "#{File.expand_path(File.join(INSTIKI_ROOT, dir))}"
}.delete_if { |dir| not File.exist?(dir) }
diff --git a/vendor/RedCloth-3.0.3/RedCloth.gemspec b/vendor/RedCloth-3.0.3/RedCloth.gemspec
deleted file mode 100644
index ca64b780..00000000
--- a/vendor/RedCloth-3.0.3/RedCloth.gemspec
+++ /dev/null
@@ -1,52 +0,0 @@
-require 'rubygems'
-spec = Gem::Specification.new do |s|
-
- ## Basic Information
-
- s.name = 'RedCloth'
- s.version = "3.0.3"
- s.platform = Gem::Platform::RUBY
- s.summary = <<-TXT
- RedCloth is a module for using Textile and Markdown in Ruby. Textile and Markdown are text formats.
- A very simple text format. Another stab at making readable text that can be converted to HTML.
- TXT
- s.description = <<-TXT
- No need to use verbose HTML to build your docs, your blogs, your pages. Textile gives you readable text while you're writing and beautiful text for your readers. And if you need to break out into HTML, Textile will allow you to do so.
-
- Textile also handles some subtleties of formatting which will enhance your document's readability:
-
- * Single- and double-quotes around words or phrases are converted to curly quotations, much easier on
- the eye. "Observe!"
-
- * Double hyphens are replaced with an em-dash. Observe -- very nice!
-
- * Single hyphens are replaced with en-dashes. Observe - so cute!
-
- * Triplets of periods become an ellipsis. Observe...
-
- * The letter 'x' becomes a dimension sign when used alone. Observe: 2 x 2.
-
- * Conversion of ==(TM)== to (TM), ==(R)== to (R), ==(C)== to (C).
-
- For more on Textile's language, hop over to "A Textile Reference":http://hobix.com/textile/. For more
- on Markdown, see "Daring Fireball's page":http://daringfireball.net/projects/markdown/.
- TXT
-
- ## Include tests, libs, docs
-
- s.files = ['bin/**/*', 'tests/**/*', 'lib/**/*', 'docs/**/*', 'run-tests.rb'].collect do |dirglob|
- Dir.glob(dirglob)
- end.flatten.delete_if {|item| item.include?("CVS")}
-
- ## Load-time details
-
- s.require_path = 'lib'
- s.autorequire = 'redcloth'
-
- ## Author and project details
-
- s.author = "Why the Lucky Stiff"
- s.email = "why@ruby-lang.org"
- s.rubyforge_project = "redcloth"
- s.homepage = "http://www.whytheluckystiff.net/ruby/redcloth/"
-end
diff --git a/vendor/RedCloth-3.0.3/install.rb b/vendor/RedCloth-3.0.3/install.rb
deleted file mode 100644
index 2313f9e9..00000000
--- a/vendor/RedCloth-3.0.3/install.rb
+++ /dev/null
@@ -1,1032 +0,0 @@
-#!/usr/local/bin/ruby
-#
-# This file is automatically generated. DO NOT MODIFY!
-#
-# install.rb
-#
-# Copyright (c) 2000-2002 Minero Aoki
-#
-# This program is free software.
-# You can distribute/modify this program under the terms of
-# the GNU Lesser General Public License version 2.
-#
-
-### begin compat.rb
-
-unless Enumerable.instance_methods.include? 'inject' then
-module Enumerable
- def inject( result )
- each do |i|
- result = yield(result, i)
- end
- result
- end
-end
-end
-
-def File.read_all( fname )
- File.open(fname, 'rb') {|f| return f.read }
-end
-
-def File.write( fname, str )
- File.open(fname, 'wb') {|f| f.write str }
-end
-
-### end compat.rb
-### begin config.rb
-
-if i = ARGV.index(/\A--rbconfig=/) then
- file = $'
- ARGV.delete_at(i)
- require file
-else
- require 'rbconfig'
-end
-
-
-class ConfigTable
-
- c = ::Config::CONFIG
-
- rubypath = c['bindir'] + '/' + c['ruby_install_name']
-
- major = c['MAJOR'].to_i
- minor = c['MINOR'].to_i
- teeny = c['TEENY'].to_i
- version = "#{major}.#{minor}"
-
- # ruby ver. >= 1.4.4?
- newpath_p = ((major >= 2) or
- ((major == 1) and
- ((minor >= 5) or
- ((minor == 4) and (teeny >= 4)))))
-
- re = Regexp.new('\A' + Regexp.quote(c['prefix']))
- subprefix = lambda {|path|
- re === path and path.sub(re, '$prefix')
- }
-
- if c['rubylibdir'] then
- # 1.6.3 < V
- stdruby = subprefix.call(c['rubylibdir'])
- siteruby = subprefix.call(c['sitedir'])
- versite = subprefix.call(c['sitelibdir'])
- sodir = subprefix.call(c['sitearchdir'])
- elsif newpath_p then
- # 1.4.4 <= V <= 1.6.3
- stdruby = "$prefix/lib/ruby/#{version}"
- siteruby = subprefix.call(c['sitedir'])
- versite = siteruby + '/' + version
- sodir = "$site-ruby/#{c['arch']}"
- else
- # V < 1.4.4
- stdruby = "$prefix/lib/ruby/#{version}"
- siteruby = "$prefix/lib/ruby/#{version}/site_ruby"
- versite = siteruby
- sodir = "$site-ruby/#{c['arch']}"
- end
-
- DESCRIPTER = [
- [ 'prefix', [ c['prefix'],
- 'path',
- 'path prefix of target environment' ] ],
- [ 'std-ruby', [ stdruby,
- 'path',
- 'the directory for standard ruby libraries' ] ],
- [ 'site-ruby-common', [ siteruby,
- 'path',
- 'the directory for version-independent non-standard ruby libraries' ] ],
- [ 'site-ruby', [ versite,
- 'path',
- 'the directory for non-standard ruby libraries' ] ],
- [ 'bin-dir', [ '$prefix/bin',
- 'path',
- 'the directory for commands' ] ],
- [ 'rb-dir', [ '$site-ruby',
- 'path',
- 'the directory for ruby scripts' ] ],
- [ 'so-dir', [ sodir,
- 'path',
- 'the directory for ruby extentions' ] ],
- [ 'data-dir', [ '$prefix/share',
- 'path',
- 'the directory for shared data' ] ],
- [ 'ruby-path', [ rubypath,
- 'path',
- 'path to set to #! line' ] ],
- [ 'ruby-prog', [ rubypath,
- 'name',
- 'the ruby program using for installation' ] ],
- [ 'make-prog', [ 'make',
- 'name',
- 'the make program to compile ruby extentions' ] ],
- [ 'without-ext', [ 'no',
- 'yes/no',
- 'does not compile/install ruby extentions' ] ]
- ]
-
- SAVE_FILE = 'config.save'
-
- def ConfigTable.each_name( &block )
- keys().each( &block )
- end
-
- def ConfigTable.keys
- DESCRIPTER.collect {|k,*dummy| k }
- end
-
- def ConfigTable.each_definition( &block )
- DESCRIPTER.each( &block )
- end
-
- def ConfigTable.get_entry( name )
- name, ent = DESCRIPTER.assoc(name)
- ent
- end
-
- def ConfigTable.get_entry!( name )
- get_entry(name) or raise ArgumentError, "no such config: #{name}"
- end
-
- def ConfigTable.add_entry( name, vals )
- ConfigTable::DESCRIPTER.push [name,vals]
- end
-
- def ConfigTable.remove_entry( name )
- get_entry name or raise ArgumentError, "no such config: #{name}"
- DESCRIPTER.delete_if {|n,arr| n == name }
- end
-
- def ConfigTable.config_key?( name )
- get_entry(name) ? true : false
- end
-
- def ConfigTable.bool_config?( name )
- ent = get_entry(name) or return false
- ent[1] == 'yes/no'
- end
-
- def ConfigTable.value_config?( name )
- ent = get_entry(name) or return false
- ent[1] != 'yes/no'
- end
-
- def ConfigTable.path_config?( name )
- ent = get_entry(name) or return false
- ent[1] == 'path'
- end
-
-
- class << self
-
- alias newobj new
-
- def new
- c = newobj()
- c.__send__ :init
- c
- end
-
- def load
- c = newobj()
- File.file? SAVE_FILE or
- raise InstallError, "#{File.basename $0} config first"
- File.foreach( SAVE_FILE ) do |line|
- k, v = line.split( '=', 2 )
- c.instance_eval {
- @table[k] = v.strip
- }
- end
- c
- end
-
- end
-
- def initialize
- @table = {}
- end
-
- def init
- DESCRIPTER.each do |k, (default, vname, desc, default2)|
- @table[k] = default
- end
- end
- private :init
-
- def save
- File.open( SAVE_FILE, 'w' ) {|f|
- @table.each do |k, v|
- f.printf "%s=%s\n", k, v if v
- end
- }
- end
-
- def []=( k, v )
- ConfigTable.config_key? k or raise InstallError, "unknown config option #{k}"
- if ConfigTable.path_config? k then
- @table[k] = (v[0,1] != '$') ? File.expand_path(v) : v
- else
- @table[k] = v
- end
- end
-
- def []( key )
- @table[key] or return nil
- @table[key].gsub( %r<\$([^/]+)> ) { self[$1] }
- end
-
- def set_raw( key, val )
- @table[key] = val
- end
-
- def get_raw( key )
- @table[key]
- end
-
-end
-
-
-class MetaConfigEnvironment
-
- def self.eval_file( file )
- return unless File.file? file
- new.instance_eval File.read_all(file), file, 1
- end
-
- private
-
- def config_names
- ConfigTable.keys
- end
-
- def config?( name )
- ConfigTable.config_key? name
- end
-
- def bool_config?( name )
- ConfigTable.bool_config? name
- end
-
- def value_config?( name )
- ConfigTable.value_config? name
- end
-
- def path_config?( name )
- ConfigTable.path_config? name
- end
-
- def add_config( name, argname, default, desc )
- ConfigTable.add_entry name,[default,argname,desc]
- end
-
- def add_path_config( name, default, desc )
- add_config name, 'path', default, desc
- end
-
- def add_bool_config( name, default, desc )
- add_config name, 'yes/no', default ? 'yes' : 'no', desc
- end
-
- def set_config_default( name, default )
- if bool_config? name then
- ConfigTable.get_entry!(name)[0] = default ? 'yes' : 'no'
- else
- ConfigTable.get_entry!(name)[0] = default
- end
- end
-
- def remove_config( name )
- ent = ConfigTable.get_entry(name)
- ConfigTable.remove_entry name
- ent
- end
-
-end
-
-### end config.rb
-### begin fileop.rb
-
-module FileOperations
-
- def mkdir_p( dname, prefix = nil )
- dname = prefix + dname if prefix
- $stderr.puts "mkdir -p #{dname}" if verbose?
- return if no_harm?
-
- # does not check '/'... it's too abnormal case
- dirs = dname.split(%r_(?=/)_)
- if /\A[a-z]:\z/i === dirs[0] then
- disk = dirs.shift
- dirs[0] = disk + dirs[0]
- end
- dirs.each_index do |idx|
- path = dirs[0..idx].join('')
- Dir.mkdir path unless dir? path
- end
- end
-
- def rm_f( fname )
- $stderr.puts "rm -f #{fname}" if verbose?
- return if no_harm?
-
- if File.exist? fname or File.symlink? fname then
- File.chmod 0777, fname
- File.unlink fname
- end
- end
-
- def rm_rf( dn )
- $stderr.puts "rm -rf #{dn}" if verbose?
- return if no_harm?
-
- Dir.chdir dn
- Dir.foreach('.') do |fn|
- next if fn == '.'
- next if fn == '..'
- if dir? fn then
- verbose_off {
- rm_rf fn
- }
- else
- verbose_off {
- rm_f fn
- }
- end
- end
- Dir.chdir '..'
- Dir.rmdir dn
- end
-
- def mv( src, dest )
- rm_f dest
- begin
- File.link src, dest
- rescue
- File.write dest, File.read_all(src)
- File.chmod File.stat(src).mode, dest
- end
- rm_f src
- end
-
- def install( from, dest, mode, prefix = nil )
- $stderr.puts "install #{from} #{dest}" if verbose?
- return if no_harm?
-
- realdest = prefix + dest if prefix
- if dir? realdest then
- realdest += '/' + File.basename(from)
- end
- str = File.read_all(from)
- if diff? str, realdest then
- verbose_off {
- rm_f realdest if File.exist? realdest
- }
- File.write realdest, str
- File.chmod mode, realdest
-
- File.open( objdir + '/InstalledFiles', 'a' ) {|f| f.puts realdest }
- end
- end
-
- def diff?( orig, targ )
- return true unless File.exist? targ
- orig != File.read_all(targ)
- end
-
- def command( str )
- $stderr.puts str if verbose?
- system str or raise RuntimeError, "'system #{str}' failed"
- end
-
- def ruby( str )
- command config('ruby-prog') + ' ' + str
- end
-
- def dir?( dname )
- # for corrupted windows stat()
- File.directory?( (dname[-1,1] == '/') ? dname : dname + '/' )
- end
-
- def all_files( dname )
- Dir.open( dname ) {|d|
- return d.find_all {|n| File.file? "#{dname}/#{n}" }
- }
- end
-
- def all_dirs( dname )
- Dir.open( dname ) {|d|
- return d.find_all {|n| dir? "#{dname}/#{n}" } - %w(. ..)
- }
- end
-
-end
-
-### end fileop.rb
-### begin base.rb
-
-class InstallError < StandardError; end
-
-
-class Installer
-
- Version = '3.1.2'
- Copyright = 'Copyright (c) 2000-2002 Minero Aoki'
-
-
- @toplevel = nil
-
- def self.declear_toplevel_installer( inst )
- @toplevel and
- raise ArgumentError, 'more than one toplevel installer decleared'
- @toplevel = inst
- end
-
- def self.toplevel_installer
- @toplevel
- end
-
-
- FILETYPES = %w( bin lib ext data )
-
- include FileOperations
-
- def initialize( config, opt, srcroot, objroot )
- @config = config
- @options = opt
- @srcdir = File.expand_path(srcroot)
- @objdir = File.expand_path(objroot)
- @currdir = '.'
- end
-
- def inspect
- "#<#{type} #{__id__}>"
- end
-
- #
- # configs/options
- #
-
- def get_config( key )
- @config[key]
- end
-
- alias config get_config
-
- def set_config( key, val )
- @config[key] = val
- end
-
- def no_harm?
- @options['no-harm']
- end
-
- def verbose?
- @options['verbose']
- end
-
- def verbose_off
- save, @options['verbose'] = @options['verbose'], false
- yield
- @options['verbose'] = save
- end
-
- #
- # srcdir/objdir
- #
-
- attr_reader :srcdir
- alias srcdir_root srcdir
- alias package_root srcdir
-
- def curr_srcdir
- "#{@srcdir}/#{@currdir}"
- end
-
- attr_reader :objdir
- alias objdir_root objdir
-
- def curr_objdir
- "#{@objdir}/#{@currdir}"
- end
-
- def srcfile( path )
- curr_srcdir + '/' + path
- end
-
- def srcexist?( path )
- File.exist? srcfile(path)
- end
-
- def srcdirectory?( path )
- dir? srcfile(path)
- end
-
- def srcfile?( path )
- File.file? srcfile(path)
- end
-
- def srcentries( path = '.' )
- Dir.open( curr_srcdir + '/' + path ) {|d|
- return d.to_a - %w(. ..) - hookfilenames
- }
- end
-
- def srcfiles( path = '.' )
- srcentries(path).find_all {|fname|
- File.file? File.join(curr_srcdir, path, fname)
- }
- end
-
- def srcdirectories( path = '.' )
- srcentries(path).find_all {|fname|
- dir? File.join(curr_srcdir, path, fname)
- }
- end
-
- def dive_into( rel )
- return unless dir? "#{@srcdir}/#{rel}"
-
- dir = File.basename(rel)
- Dir.mkdir dir unless dir? dir
- save = Dir.pwd
- Dir.chdir dir
- $stderr.puts '---> ' + rel if verbose?
- @currdir = rel
- yield
- Dir.chdir save
- $stderr.puts '<--- ' + rel if verbose?
- @currdir = File.dirname(rel)
- end
-
- #
- # config
- #
-
- def exec_config
- exec_task_traverse 'config'
- end
-
- def config_dir_bin( rel )
- end
-
- def config_dir_lib( rel )
- end
-
- def config_dir_ext( rel )
- extconf if extdir? curr_srcdir
- end
-
- def extconf
- opt = @options['config-opt'].join(' ')
- command "#{config('ruby-prog')} #{curr_srcdir}/extconf.rb #{opt}"
- end
-
- def config_dir_data( rel )
- end
-
- #
- # setup
- #
-
- def exec_setup
- exec_task_traverse 'setup'
- end
-
- def setup_dir_bin( relpath )
- all_files( curr_srcdir ).each do |fname|
- add_rubypath "#{curr_srcdir}/#{fname}"
- end
- end
-
- SHEBANG_RE = /\A\#!\s*\S*ruby\S*/
-
- def add_rubypath( path )
- $stderr.puts %Q if verbose?
- return if no_harm?
-
- tmpfile = File.basename(path) + '.tmp'
- begin
- File.open( path ) {|r|
- File.open( tmpfile, 'w' ) {|w|
- first = r.gets
- return unless SHEBANG_RE === first # reject '/usr/bin/env ruby'
-
- w.print first.sub( SHEBANG_RE, '#!' + config('ruby-path') )
- w.write r.read
- } }
- mv tmpfile, File.basename(path)
- ensure
- rm_f tmpfile if File.exist? tmpfile
- end
- end
-
- def setup_dir_lib( relpath )
- end
-
- def setup_dir_ext( relpath )
- if extdir? curr_srcdir then
- make
- end
- end
-
- def make
- command config('make-prog')
- end
-
- def setup_dir_data( relpath )
- end
-
- #
- # install
- #
-
- def exec_install
- exec_task_traverse 'install'
- end
-
- def install_dir_bin( rel )
- install_files targfiles, config('bin-dir') + '/' + rel, 0755
- end
-
- def install_dir_lib( rel )
- install_files targfiles, config('rb-dir') + '/' + rel, 0644
- begin
- require 'rdoc/rdoc'
- ri_site = true
- if RDOC_VERSION =~ /^0\./
- require 'rdoc/options'
- unless Options::OptionList::OPTION_LIST.assoc('--ri-site')
- ri_site = false
- end
- end
- if ri_site
- r = RDoc::RDoc.new
- r.document(%w{--ri-site})
- end
- rescue
- puts "** Unable to install Ri documentation for RedCloth **"
- end
- end
-
- def install_dir_ext( rel )
- if extdir? curr_srcdir then
- install_dir_ext_main File.dirname(rel)
- end
- end
-
- def install_dir_ext_main( rel )
- install_files allext('.'), config('so-dir') + '/' + rel, 0555
- end
-
- def install_dir_data( rel )
- install_files targfiles, config('data-dir') + '/' + rel, 0644
- end
-
- def install_files( list, dest, mode )
- mkdir_p dest, @options['install-prefix']
- list.each do |fname|
- install fname, dest, mode, @options['install-prefix']
- end
- end
-
- def targfiles
- (targfilenames() - hookfilenames()).collect {|fname|
- File.exist?(fname) ? fname : File.join(curr_srcdir(), fname)
- }
- end
-
- def targfilenames
- [ curr_srcdir(), '.' ].inject([]) {|ret, dir|
- ret | all_files(dir)
- }
- end
-
- def hookfilenames
- %w( pre-%s post-%s pre-%s.rb post-%s.rb ).collect {|fmt|
- %w( config setup install clean ).collect {|t| sprintf fmt, t }
- }.flatten
- end
-
- def allext( dir )
- _allext(dir) or raise InstallError,
- "no extention exists: Have you done 'ruby #{$0} setup' ?"
- end
-
- DLEXT = /\.#{ ::Config::CONFIG['DLEXT'] }\z/
-
- def _allext( dir )
- Dir.open( dir ) {|d|
- return d.find_all {|fname| DLEXT === fname }
- }
- end
-
- #
- # clean
- #
-
- def exec_clean
- exec_task_traverse 'clean'
- rm_f 'config.save'
- rm_f 'InstalledFiles'
- end
-
- def clean_dir_bin( rel )
- end
-
- def clean_dir_lib( rel )
- end
-
- def clean_dir_ext( rel )
- clean
- end
-
- def clean
- command config('make-prog') + ' clean' if File.file? 'Makefile'
- end
-
- def clean_dir_data( rel )
- end
-
- #
- # lib
- #
-
- def exec_task_traverse( task )
- run_hook 'pre-' + task
- FILETYPES.each do |type|
- if config('without-ext') == 'yes' and type == 'ext' then
- $stderr.puts 'skipping ext/* by user option' if verbose?
- next
- end
- traverse task, type, task + '_dir_' + type
- end
- run_hook 'post-' + task
- end
-
- def traverse( task, rel, mid )
- dive_into( rel ) {
- run_hook 'pre-' + task
- __send__ mid, rel.sub( %r_\A.*?(?:/|\z)_, '' )
- all_dirs( curr_srcdir ).each do |d|
- traverse task, rel + '/' + d, mid
- end
- run_hook 'post-' + task
- }
- end
-
- def run_hook( name )
- try_run_hook curr_srcdir + '/' + name or
- try_run_hook curr_srcdir + '/' + name + '.rb'
- end
-
- def try_run_hook( fname )
- return false unless File.file? fname
-
- env = self.dup
- begin
- env.instance_eval File.read_all(fname), fname, 1
- rescue
- raise InstallError, "hook #{fname} failed:\n" + $!.message
- end
- true
- end
-
- def extdir?( dir )
- File.exist? dir + '/MANIFEST'
- end
-
-end
-
-### end base.rb
-### begin toplevel.rb
-
-class ToplevelInstaller < Installer
-
- TASKS = [
- [ 'config', 'saves your configurations' ],
- [ 'show', 'shows current configuration' ],
- [ 'setup', 'compiles extention or else' ],
- [ 'install', 'installs files' ],
- [ 'clean', "does `make clean' for each extention" ]
- ]
-
-
- def initialize( root )
- super nil, {'verbose' => true}, root, '.'
- Installer.declear_toplevel_installer self
- end
-
-
- def execute
- run_metaconfigs
-
- case task = parsearg_global()
- when 'config'
- @config = ConfigTable.new
- else
- @config = ConfigTable.load
- end
- parsearg_TASK task
-
- exectask task
- end
-
-
- def run_metaconfigs
- MetaConfigEnvironment.eval_file "#{srcdir_root}/#{metaconfig}"
- end
-
- def metaconfig
- 'metaconfig'
- end
-
-
- def exectask( task )
- if task == 'show' then
- exec_show
- else
- try task
- end
- end
-
- def try( task )
- $stderr.printf "#{File.basename $0}: entering %s phase...\n", task if verbose?
- begin
- __send__ 'exec_' + task
- rescue
- $stderr.printf "%s failed\n", task
- raise
- end
- $stderr.printf "#{File.basename $0}: %s done.\n", task if verbose?
- end
-
- #
- # processing arguments
- #
-
- def parsearg_global
- task_re = /\A(?:#{TASKS.collect {|i| i[0] }.join '|'})\z/
-
- while arg = ARGV.shift do
- case arg
- when /\A\w+\z/
- task_re === arg or raise InstallError, "wrong task: #{arg}"
- return arg
-
- when '-q', '--quiet'
- @options['verbose'] = false
-
- when '--verbose'
- @options['verbose'] = true
-
- when '-h', '--help'
- print_usage $stdout
- exit 0
-
- when '-v', '--version'
- puts "#{File.basename $0} version #{Version}"
- exit 0
-
- when '--copyright'
- puts Copyright
- exit 0
-
- else
- raise InstallError, "unknown global option '#{arg}'"
- end
- end
-
- raise InstallError, 'no task or global option given'
- end
-
-
- def parsearg_TASK( task )
- mid = "parsearg_#{task}"
- if respond_to? mid, true then
- __send__ mid
- else
- ARGV.empty? or
- raise InstallError, "#{task}: unknown options: #{ARGV.join ' '}"
- end
- end
-
- def parsearg_config
- re = /\A--(#{ConfigTable.keys.join '|'})(?:=(.*))?\z/
- @options['config-opt'] = []
-
- while i = ARGV.shift do
- if /\A--?\z/ === i then
- @options['config-opt'] = ARGV.dup
- break
- end
- m = re.match(i) or raise InstallError, "config: unknown option #{i}"
- name, value = m.to_a[1,2]
- if value then
- if ConfigTable.bool_config?(name) then
- /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i === value or raise InstallError, "config: --#{name} allows only yes/no for argument"
- value = (/\Ay(es)?|\At(rue)/i === value) ? 'yes' : 'no'
- end
- else
- ConfigTable.bool_config?(name) or raise InstallError, "config: --#{name} requires argument"
- value = 'yes'
- end
- @config[name] = value
- end
- end
-
- def parsearg_install
- @options['no-harm'] = false
- @options['install-prefix'] = ''
- while a = ARGV.shift do
- case a
- when /\A--no-harm\z/
- @options['no-harm'] = true
- when /\A--prefix=(.*)\z/
- path = $1
- path = File.expand_path(path) unless path[0,1] == '/'
- @options['install-prefix'] = path
- else
- raise InstallError, "install: unknown option #{a}"
- end
- end
- end
-
-
- def print_usage( out )
- out.puts
- out.puts 'Usage:'
- out.puts " ruby #{File.basename $0} "
- out.puts " ruby #{File.basename $0} [] []"
-
- fmt = " %-20s %s\n"
- out.puts
- out.puts 'Global options:'
- out.printf fmt, '-q,--quiet', 'suppress message outputs'
- out.printf fmt, ' --verbose', 'output messages verbosely'
- out.printf fmt, '-h,--help', 'print this message'
- out.printf fmt, '-v,--version', 'print version and quit'
- out.printf fmt, '--copyright', 'print copyright and quit'
-
- out.puts
- out.puts 'Tasks:'
- TASKS.each do |name, desc|
- out.printf " %-10s %s\n", name, desc
- end
-
- out.puts
- out.puts 'Options for config:'
- ConfigTable.each_definition do |name, (default, arg, desc, default2)|
- out.printf " %-20s %s [%s]\n",
- '--'+ name + (ConfigTable.bool_config?(name) ? '' : '='+arg),
- desc,
- default2 || default
- end
- out.printf " %-20s %s [%s]\n",
- '--rbconfig=path', 'your rbconfig.rb to load', "running ruby's"
-
- out.puts
- out.puts 'Options for install:'
- out.printf " %-20s %s [%s]\n",
- '--no-harm', 'only display what to do if given', 'off'
-
- out.puts
- end
-
- #
- # config
- #
-
- def exec_config
- super
- @config.save
- end
-
- #
- # show
- #
-
- def exec_show
- ConfigTable.each_name do |k|
- v = @config.get_raw(k)
- if not v or v.empty? then
- v = '(not specified)'
- end
- printf "%-10s %s\n", k, v
- end
- end
-
-end
-
-### end toplevel.rb
-
-if $0 == __FILE__ then
- begin
- installer = ToplevelInstaller.new( Dir.pwd )
- installer.execute
- rescue
- raise if $DEBUG
- $stderr.puts $!.message
- $stderr.puts "try 'ruby #{$0} --help' for usage"
- exit 1
- end
-end
diff --git a/vendor/RedCloth-3.0.3/bin/redcloth b/vendor/RedCloth-3.0.4/bin/redcloth
similarity index 70%
rename from vendor/RedCloth-3.0.3/bin/redcloth
rename to vendor/RedCloth-3.0.4/bin/redcloth
index 81abf7db..ae210b6a 100644
--- a/vendor/RedCloth-3.0.3/bin/redcloth
+++ b/vendor/RedCloth-3.0.4/bin/redcloth
@@ -1,3 +1,3 @@
-#!/usr/local/bin/ruby18
+#!/usr/bin/ruby18
require 'redcloth'
puts RedCloth.new( ARGF.read ).to_html
diff --git a/vendor/RedCloth-3.0.3/doc/CHANGELOG b/vendor/RedCloth-3.0.4/doc/CHANGELOG
similarity index 92%
rename from vendor/RedCloth-3.0.3/doc/CHANGELOG
rename to vendor/RedCloth-3.0.4/doc/CHANGELOG
index 7b5f9cf3..0581447c 100644
--- a/vendor/RedCloth-3.0.3/doc/CHANGELOG
+++ b/vendor/RedCloth-3.0.4/doc/CHANGELOG
@@ -1,4 +1,15 @@
--- %YAML:1.0
+- version: 3.0.4
+ date: 2005-02-18
+ changes:
+ - The caps class doesn't swallow spaces.
+ - Horizontal rules required to be on an empty line.
+ - Hard breaks don't screw with Markdown headers any longer.
+ - Fixed error triggered by complex lists.
+ - Inline markups need to be butted up against enclosing text, no spaces.
+ - Fixed problem with intermingled single and double quotes.
+ - Brought back lite_mode.
+
- version: 3.0.3
date: 2005-02-06
changes:
diff --git a/vendor/RedCloth-3.0.3/doc/COPYING b/vendor/RedCloth-3.0.4/doc/COPYING
similarity index 100%
rename from vendor/RedCloth-3.0.3/doc/COPYING
rename to vendor/RedCloth-3.0.4/doc/COPYING
diff --git a/vendor/RedCloth-3.0.3/doc/README b/vendor/RedCloth-3.0.4/doc/README
similarity index 91%
rename from vendor/RedCloth-3.0.3/doc/README
rename to vendor/RedCloth-3.0.4/doc/README
index 1ae4560c..1c0b0f38 100644
--- a/vendor/RedCloth-3.0.3/doc/README
+++ b/vendor/RedCloth-3.0.4/doc/README
@@ -4,9 +4,7 @@ p=. !redcloth3-title.png!
h4. Get RedCloth 3
-p(example1). *Stable version:* "2.0.11":http://rubyforge.org/frs/download.php/698/redcloth-2.0.11.tar.gz
-
-p(example1). *Unstable version:* "3.0.2":http://rubyforge.org/frs/download.php/2852/RedCloth-3.0.2.tar.gz
+p(example1). *Stable version:* "3.0.3":http://rubyforge.org/frs/download.php/2896/RedCloth-3.0.3.tar.gz
Take a complete tour of Textile at "A Textile Reference":http://hobix.com/textile/.
@@ -91,7 +89,7 @@ To install RedCloth via RubyGems:
gem install RedCloth
-Or "download RedCloth":http://rubyforge.org/frs/download.php/2852/RedCloth-3.0.2.tar.gz and simply run the install.rb like so:
+Or "download RedCloth":http://rubyforge.org/frs/download.php/2896/RedCloth-3.0.3.tar.gz and simply run the install.rb like so:
ruby install.rb config
diff --git a/vendor/RedCloth-3.0.3/doc/REFERENCE b/vendor/RedCloth-3.0.4/doc/REFERENCE
similarity index 98%
rename from vendor/RedCloth-3.0.3/doc/REFERENCE
rename to vendor/RedCloth-3.0.4/doc/REFERENCE
index a3e5bec0..c7236e89 100644
--- a/vendor/RedCloth-3.0.3/doc/REFERENCE
+++ b/vendor/RedCloth-3.0.4/doc/REFERENCE
@@ -24,9 +24,9 @@
if it's found in a @pre@ or @code@ block.
- !!example "I am very serious.\n\n
diff --git a/vendor/RedCloth-3.0.3/tests/images.yml b/vendor/RedCloth-3.0.4/tests/images.yml
similarity index 100%
rename from vendor/RedCloth-3.0.3/tests/images.yml
rename to vendor/RedCloth-3.0.4/tests/images.yml
diff --git a/vendor/RedCloth-3.0.3/tests/instiki.yml b/vendor/RedCloth-3.0.4/tests/instiki.yml
similarity index 100%
rename from vendor/RedCloth-3.0.3/tests/instiki.yml
rename to vendor/RedCloth-3.0.4/tests/instiki.yml
diff --git a/vendor/RedCloth-3.0.3/tests/links.yml b/vendor/RedCloth-3.0.4/tests/links.yml
similarity index 100%
rename from vendor/RedCloth-3.0.3/tests/links.yml
rename to vendor/RedCloth-3.0.4/tests/links.yml
diff --git a/vendor/RedCloth-3.0.3/tests/lists.yml b/vendor/RedCloth-3.0.4/tests/lists.yml
similarity index 100%
rename from vendor/RedCloth-3.0.3/tests/lists.yml
rename to vendor/RedCloth-3.0.4/tests/lists.yml
diff --git a/vendor/RedCloth-3.0.3/tests/markdown.yml b/vendor/RedCloth-3.0.4/tests/markdown.yml
similarity index 100%
rename from vendor/RedCloth-3.0.3/tests/markdown.yml
rename to vendor/RedCloth-3.0.4/tests/markdown.yml
diff --git a/vendor/RedCloth-3.0.3/tests/poignant.yml b/vendor/RedCloth-3.0.4/tests/poignant.yml
similarity index 100%
rename from vendor/RedCloth-3.0.3/tests/poignant.yml
rename to vendor/RedCloth-3.0.4/tests/poignant.yml
diff --git a/vendor/RedCloth-3.0.3/tests/table.yml b/vendor/RedCloth-3.0.4/tests/table.yml
similarity index 95%
rename from vendor/RedCloth-3.0.3/tests/table.yml
rename to vendor/RedCloth-3.0.4/tests/table.yml
index bf5059e1..3ce974dd 100644
--- a/vendor/RedCloth-3.0.3/tests/table.yml
+++ b/vendor/RedCloth-3.0.4/tests/table.yml
@@ -39,28 +39,28 @@ out: |-
11/18/04
11/18/04
070
-
XML spec complete
+
XML spec complete
11/29/04
11/29/04
011
-
XML spec complete (KH is on schedule)
+
XML spec complete (KH is on schedule)
11/29/04
11/29/04
051
-
XML spec complete (KH is on schedule)
+
XML spec complete (KH is on schedule)
11/29/04
11/29/04
081
-
XML spec complete (KH is on schedule)
+
XML spec complete (KH is on schedule)
diff --git a/vendor/RedCloth-3.0.3/tests/textism.yml b/vendor/RedCloth-3.0.4/tests/textism.yml
similarity index 97%
rename from vendor/RedCloth-3.0.3/tests/textism.yml
rename to vendor/RedCloth-3.0.4/tests/textism.yml
index 5489c04d..1e6f8d6b 100644
--- a/vendor/RedCloth-3.0.3/tests/textism.yml
+++ b/vendor/RedCloth-3.0.4/tests/textism.yml
@@ -71,6 +71,12 @@ out:
diff --git a/lib/page_renderer.rb b/lib/page_renderer.rb
index 374da3f3..f47238f4 100644
--- a/lib/page_renderer.rb
+++ b/lib/page_renderer.rb
@@ -20,11 +20,12 @@ class PageRenderer
def revision=(r)
@revision = r
- @wiki_words_cache = @wiki_includes_cache = @wiki_references_cache = nil
+ @display_content = @display_published = @wiki_words_cache = @wiki_includes_cache =
+ @wiki_references_cache = nil
end
- def display_content
- @display_content ||= render
+ def display_content(update_references = false)
+ @display_content ||= render(:update_references => update_references)
end
def display_content_for_export
@@ -87,12 +88,21 @@ class PageRenderer
private
def render(options = {})
- result = WikiContent.new(@revision, @@url_generator, options).render!
+
+ rendering_result = WikiContent.new(@revision, @@url_generator, options).render!
+
+ if options[:update_references]
+ update_references(rendering_result)
+ end
+ rendering_result
+ end
+
+ def update_references(rendering_result)
WikiReference.delete_all ['page_id = ?', @revision.page_id]
references = @revision.page.wiki_references
- wiki_word_chunks = result.find_chunks(WikiChunk::WikiLink)
+ wiki_word_chunks = rendering_result.find_chunks(WikiChunk::WikiLink)
wiki_words = wiki_word_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
wiki_words.each do |referenced_name|
@@ -105,17 +115,16 @@ class PageRenderer
references.create :referenced_name => referenced_name, :link_type => link_type
end
- include_chunks = result.find_chunks(Include)
+ include_chunks = rendering_result.find_chunks(Include)
includes = include_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
includes.each do |included_page_name|
references.create :referenced_name => included_page_name,
:link_type => WikiReference::INCLUDED_PAGE
end
- categories = result.find_chunks(Category).map { |cat| cat.list }.flatten
+ categories = rendering_result.find_chunks(Category).map { |cat| cat.list }.flatten
categories.each do |category|
references.create :referenced_name => category, :link_type => WikiReference::CATEGORY
end
- result
end
end
diff --git a/script/reset_references b/script/reset_references
index 0e21b0c9..176f3430 100644
--- a/script/reset_references
+++ b/script/reset_references
@@ -16,7 +16,7 @@ Web.find_all.each do |web|
web.pages.find(:all, :order => 'name').each do |page|
$stderr.puts "Processing page '#{page.name}'"
begin
- PageRenderer.new(page.current_revision).display_content
+ PageRenderer.new(page.current_revision).display_content(update_references = true)
rescue => e
puts e
puts e.backtrace
diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb
index 8be34cb4..9d39fa23 100755
--- a/test/functional/wiki_controller_test.rb
+++ b/test/functional/wiki_controller_test.rb
@@ -53,6 +53,9 @@ class WikiControllerTest < Test::Unit::TestCase
assert_success
assert_equal %w(AnAuthor BreakingTheOrder DavidHeinemeierHansson Guest Me TreeHugger),
r.template_objects['authors']
+ page_names_by_author = r.template_objects['page_names_by_author']
+ assert_equal r.template_objects['authors'], page_names_by_author.keys.sort
+ assert_equal %w(FirstPage HomePage), page_names_by_author['DavidHeinemeierHansson']
end
def test_cancel_edit
diff --git a/test/unit/web_test.rb b/test/unit/web_test.rb
index 875c0bb3..57f47ea7 100644
--- a/test/unit/web_test.rb
+++ b/test/unit/web_test.rb
@@ -86,6 +86,14 @@ class WebTest < Test::Unit::TestCase
@web.select.orphaned_pages.collect{ |page| page.name }.sort
end
+ def test_page_names_by_author
+ page_names_by_author = webs(:test_wiki).page_names_by_author
+ assert_equal %w(AnAuthor DavidHeinemeierHansson Guest Me TreeHugger),
+ page_names_by_author.keys.sort
+ assert_equal %w(FirstPage HomePage), page_names_by_author['DavidHeinemeierHansson']
+ assert_equal %w(Oak), page_names_by_author['TreeHugger']
+ end
+
private
def add_sample_pages
From 61776995b6a3a15a368278b7d7712f687eb35ffd Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Wed, 28 Sep 2005 02:03:28 +0000
Subject: [PATCH 66/84] Fixes for MySQL compatibility
---
db/wiki_references.erbsql | 2 +-
script/import_storage | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/db/wiki_references.erbsql b/db/wiki_references.erbsql
index 5dbe72d6..6b7115ce 100644
--- a/db/wiki_references.erbsql
+++ b/db/wiki_references.erbsql
@@ -4,6 +4,6 @@ CREATE TABLE wiki_references (
updated_at <%= @datetime %> NOT NULL,
page_id INTEGER NOT NULL,
- referenced_name VARCHAR NOT NULL,
+ referenced_name VARCHAR(60) NOT NULL,
link_type CHAR(1) NOT NULL
) <%= create_options %>;
\ No newline at end of file
diff --git a/script/import_storage b/script/import_storage
index a999d0ca..690a192e 100755
--- a/script/import_storage
+++ b/script/import_storage
@@ -183,7 +183,7 @@ File.open(OPTIONS[:outfile], 'w') { |outfile|
puts "Web #{web_name} has #{web.pages.keys.size} pages"
web.pages.each_pair do |page_name, page|
- outfile.puts "BEGIN TRANSACTION;"
+ outfile.puts "BEGIN;"
outfile.puts sql_insert(:pages, {
:id => next_id(:page),
From 9ea6e6ae65dc96fde00819a93fa6dad3be272726 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Wed, 28 Sep 2005 04:12:11 +0000
Subject: [PATCH 67/84] Downgrading RedCloth back to 3.0.3 (3.0.4 is said to be
buggy)
---
CHANGELOG | 3 +-
instiki.gemspec | 2 +-
rakefile.rb | 71 -
test/test_helper.rb | 4 +-
vendor/RedCloth-3.0.3/RedCloth.gemspec | 52 +
.../bin/redcloth | 2 +-
.../doc/CHANGELOG | 11 -
.../doc/COPYING | 0
.../doc/README | 6 +-
.../doc/REFERENCE | 8 +-
.../doc/make.rb | 0
vendor/RedCloth-3.0.3/install.rb | 1032 +++++++++++++
.../lib/redcloth.rb | 137 +-
.../run-tests.rb | 4 +-
.../tests/code.yml | 0
.../tests/images.yml | 0
.../tests/instiki.yml | 0
.../tests/links.yml | 0
.../tests/lists.yml | 0
.../tests/markdown.yml | 0
.../tests/poignant.yml | 0
.../tests/table.yml | 8 +-
.../tests/textism.yml | 9 -
vendor/RedCloth-3.0.4/setup.rb | 1376 -----------------
vendor/RedCloth-3.0.4/tests/hard_breaks.yml | 26 -
25 files changed, 1162 insertions(+), 1589 deletions(-)
create mode 100644 vendor/RedCloth-3.0.3/RedCloth.gemspec
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/bin/redcloth (70%)
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/doc/CHANGELOG (92%)
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/doc/COPYING (100%)
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/doc/README (91%)
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/doc/REFERENCE (98%)
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/doc/make.rb (100%)
create mode 100644 vendor/RedCloth-3.0.3/install.rb
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/lib/redcloth.rb (94%)
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/run-tests.rb (83%)
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/tests/code.yml (100%)
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/tests/images.yml (100%)
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/tests/instiki.yml (100%)
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/tests/links.yml (100%)
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/tests/lists.yml (100%)
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/tests/markdown.yml (100%)
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/tests/poignant.yml (100%)
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/tests/table.yml (95%)
rename vendor/{RedCloth-3.0.4 => RedCloth-3.0.3}/tests/textism.yml (97%)
delete mode 100644 vendor/RedCloth-3.0.4/setup.rb
delete mode 100644 vendor/RedCloth-3.0.4/tests/hard_breaks.yml
diff --git a/CHANGELOG b/CHANGELOG
index d093c887..6b2dcbda 100755
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,5 @@
- * instiki-ar
+ * instiki-ar:
SQL-based backend (ActiveRecord)
- Upgrade to RedCloth 3.0.4
Replaced internal link generator with routing
Fixed --daemon option
diff --git a/instiki.gemspec b/instiki.gemspec
index caeee714..c65ac414 100755
--- a/instiki.gemspec
+++ b/instiki.gemspec
@@ -24,7 +24,7 @@ spec = Gem::Specification.new do |s|
s.has_rdoc = false
- s.add_dependency('RedCloth', '= 3.0.4')
+ s.add_dependency('RedCloth', '= 3.0.3')
s.add_dependency('rubyzip', '= 0.5.8')
s.add_dependency('rails', '= 0.13.1')
s.add_dependency('sqlite3-ruby', '= 1.1.0')
diff --git a/rakefile.rb b/rakefile.rb
index af9c997f..033b052f 100755
--- a/rakefile.rb
+++ b/rakefile.rb
@@ -20,36 +20,12 @@ desc "Generate API documentation, show coding stats"
task :doc => [ :appdoc, :stats ]
-# Look up tests for recently modified sources.
-def recent_tests(source_pattern, test_path, touched_since = 10.minutes.ago)
- FileList[source_pattern].map do |path|
- if File.mtime(path) > touched_since
- test = "#{test_path}/#{File.basename(path, '.rb')}_test.rb"
- test if File.exists?(test)
- end
- end.compact
-end
-
-desc 'Test recent changes.'
-Rake::TestTask.new(:recent => [ :clone_structure_to_test ]) do |t|
- since = TEST_CHANGES_SINCE
- touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } +
- recent_tests('app/models/*.rb', 'test/unit', since) +
- recent_tests('app/controllers/*.rb', 'test/functional', since)
-
- t.libs << 'test'
- t.verbose = true
- t.test_files = touched.uniq
-end
-task :test_recent => [ :clone_structure_to_test ]
-
desc "Run the unit tests in test/unit"
Rake::TestTask.new("test_units") { |t|
t.libs << "test"
t.pattern = 'test/unit/**/*_test.rb'
t.verbose = true
}
-task :test_units => [ :clone_structure_to_test ]
desc "Run the functional tests in test/functional"
Rake::TestTask.new("test_functional") { |t|
@@ -57,7 +33,6 @@ Rake::TestTask.new("test_functional") { |t|
t.pattern = 'test/functional/**/*_test.rb'
t.verbose = true
}
-task :test_functional => [ :clone_structure_to_test ]
desc "Generate documentation for the application"
Rake::RDocTask.new("appdoc") { |rdoc|
@@ -118,52 +93,6 @@ task :stats => [ :environment ] do
).to_s
end
-desc "Recreate the test databases from the development structure"
-task :clone_structure_to_test => [ :db_structure_dump, :purge_test_database ] do
- abcs = ActiveRecord::Base.configurations
- case abcs["test"]["adapter"]
- when "mysql"
- ActiveRecord::Base.establish_connection(:test)
- ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
- IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table|
- ActiveRecord::Base.connection.execute(table)
- end
- when "postgresql"
- ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
- ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
- ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
- `psql -U "#{abcs["test"]["username"]}" -f db/#{RAILS_ENV}_structure.sql #{abcs["test"]["database"]}`
- when "sqlite", "sqlite3"
- `#{abcs[RAILS_ENV]["adapter"]} #{abcs["test"]["dbfile"]} < db/#{RAILS_ENV}_structure.sql`
- when "sqlserver"
- `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
- else
- raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
- end
-end
-
-desc "Dump the database structure to a SQL file"
-task :db_structure_dump => :environment do
- abcs = ActiveRecord::Base.configurations
- case abcs[RAILS_ENV]["adapter"]
- when "mysql"
- ActiveRecord::Base.establish_connection(abcs[RAILS_ENV])
- File.open("db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
- when "postgresql"
- ENV['PGHOST'] = abcs[RAILS_ENV]["host"] if abcs[RAILS_ENV]["host"]
- ENV['PGPORT'] = abcs[RAILS_ENV]["port"].to_s if abcs[RAILS_ENV]["port"]
- ENV['PGPASSWORD'] = abcs[RAILS_ENV]["password"].to_s if abcs[RAILS_ENV]["password"]
- `pg_dump -U "#{abcs[RAILS_ENV]["username"]}" -s -x -O -f db/#{RAILS_ENV}_structure.sql #{abcs[RAILS_ENV]["database"]}`
- when "sqlite", "sqlite3"
- `#{abcs[RAILS_ENV]["adapter"]} #{abcs[RAILS_ENV]["dbfile"]} .schema > db/#{RAILS_ENV}_structure.sql`
- when "sqlserver"
- `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /f db\\#{RAILS_ENV}_structure.sql /q /A /r`
- `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /F db\ /q /A /r`
- else
- raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
- end
-end
-
desc "Empty the test database"
task :purge_test_database => :environment do
abcs = ActiveRecord::Base.configurations
diff --git a/test/test_helper.rb b/test/test_helper.rb
index adf78cf2..f23bebeb 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -1,8 +1,8 @@
-ENV["RAILS_ENV"] = "test"
+ENV['RAILS_ENV'] = 'test'
# Expand the path to environment so that Ruby does not load it multiple times
# File.expand_path can be removed if Ruby 1.9 is in use.
-require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
+require File.expand_path(File.dirname(__FILE__) + '/../config/environment')
require 'application'
require 'test/unit'
diff --git a/vendor/RedCloth-3.0.3/RedCloth.gemspec b/vendor/RedCloth-3.0.3/RedCloth.gemspec
new file mode 100644
index 00000000..ca64b780
--- /dev/null
+++ b/vendor/RedCloth-3.0.3/RedCloth.gemspec
@@ -0,0 +1,52 @@
+require 'rubygems'
+spec = Gem::Specification.new do |s|
+
+ ## Basic Information
+
+ s.name = 'RedCloth'
+ s.version = "3.0.3"
+ s.platform = Gem::Platform::RUBY
+ s.summary = <<-TXT
+ RedCloth is a module for using Textile and Markdown in Ruby. Textile and Markdown are text formats.
+ A very simple text format. Another stab at making readable text that can be converted to HTML.
+ TXT
+ s.description = <<-TXT
+ No need to use verbose HTML to build your docs, your blogs, your pages. Textile gives you readable text while you're writing and beautiful text for your readers. And if you need to break out into HTML, Textile will allow you to do so.
+
+ Textile also handles some subtleties of formatting which will enhance your document's readability:
+
+ * Single- and double-quotes around words or phrases are converted to curly quotations, much easier on
+ the eye. "Observe!"
+
+ * Double hyphens are replaced with an em-dash. Observe -- very nice!
+
+ * Single hyphens are replaced with en-dashes. Observe - so cute!
+
+ * Triplets of periods become an ellipsis. Observe...
+
+ * The letter 'x' becomes a dimension sign when used alone. Observe: 2 x 2.
+
+ * Conversion of ==(TM)== to (TM), ==(R)== to (R), ==(C)== to (C).
+
+ For more on Textile's language, hop over to "A Textile Reference":http://hobix.com/textile/. For more
+ on Markdown, see "Daring Fireball's page":http://daringfireball.net/projects/markdown/.
+ TXT
+
+ ## Include tests, libs, docs
+
+ s.files = ['bin/**/*', 'tests/**/*', 'lib/**/*', 'docs/**/*', 'run-tests.rb'].collect do |dirglob|
+ Dir.glob(dirglob)
+ end.flatten.delete_if {|item| item.include?("CVS")}
+
+ ## Load-time details
+
+ s.require_path = 'lib'
+ s.autorequire = 'redcloth'
+
+ ## Author and project details
+
+ s.author = "Why the Lucky Stiff"
+ s.email = "why@ruby-lang.org"
+ s.rubyforge_project = "redcloth"
+ s.homepage = "http://www.whytheluckystiff.net/ruby/redcloth/"
+end
diff --git a/vendor/RedCloth-3.0.4/bin/redcloth b/vendor/RedCloth-3.0.3/bin/redcloth
similarity index 70%
rename from vendor/RedCloth-3.0.4/bin/redcloth
rename to vendor/RedCloth-3.0.3/bin/redcloth
index ae210b6a..81abf7db 100644
--- a/vendor/RedCloth-3.0.4/bin/redcloth
+++ b/vendor/RedCloth-3.0.3/bin/redcloth
@@ -1,3 +1,3 @@
-#!/usr/bin/ruby18
+#!/usr/local/bin/ruby18
require 'redcloth'
puts RedCloth.new( ARGF.read ).to_html
diff --git a/vendor/RedCloth-3.0.4/doc/CHANGELOG b/vendor/RedCloth-3.0.3/doc/CHANGELOG
similarity index 92%
rename from vendor/RedCloth-3.0.4/doc/CHANGELOG
rename to vendor/RedCloth-3.0.3/doc/CHANGELOG
index 0581447c..7b5f9cf3 100644
--- a/vendor/RedCloth-3.0.4/doc/CHANGELOG
+++ b/vendor/RedCloth-3.0.3/doc/CHANGELOG
@@ -1,15 +1,4 @@
--- %YAML:1.0
-- version: 3.0.4
- date: 2005-02-18
- changes:
- - The caps class doesn't swallow spaces.
- - Horizontal rules required to be on an empty line.
- - Hard breaks don't screw with Markdown headers any longer.
- - Fixed error triggered by complex lists.
- - Inline markups need to be butted up against enclosing text, no spaces.
- - Fixed problem with intermingled single and double quotes.
- - Brought back lite_mode.
-
- version: 3.0.3
date: 2005-02-06
changes:
diff --git a/vendor/RedCloth-3.0.4/doc/COPYING b/vendor/RedCloth-3.0.3/doc/COPYING
similarity index 100%
rename from vendor/RedCloth-3.0.4/doc/COPYING
rename to vendor/RedCloth-3.0.3/doc/COPYING
diff --git a/vendor/RedCloth-3.0.4/doc/README b/vendor/RedCloth-3.0.3/doc/README
similarity index 91%
rename from vendor/RedCloth-3.0.4/doc/README
rename to vendor/RedCloth-3.0.3/doc/README
index 1c0b0f38..1ae4560c 100644
--- a/vendor/RedCloth-3.0.4/doc/README
+++ b/vendor/RedCloth-3.0.3/doc/README
@@ -4,7 +4,9 @@ p=. !redcloth3-title.png!
h4. Get RedCloth 3
-p(example1). *Stable version:* "3.0.3":http://rubyforge.org/frs/download.php/2896/RedCloth-3.0.3.tar.gz
+p(example1). *Stable version:* "2.0.11":http://rubyforge.org/frs/download.php/698/redcloth-2.0.11.tar.gz
+
+p(example1). *Unstable version:* "3.0.2":http://rubyforge.org/frs/download.php/2852/RedCloth-3.0.2.tar.gz
Take a complete tour of Textile at "A Textile Reference":http://hobix.com/textile/.
@@ -89,7 +91,7 @@ To install RedCloth via RubyGems:
gem install RedCloth
-Or "download RedCloth":http://rubyforge.org/frs/download.php/2896/RedCloth-3.0.3.tar.gz and simply run the install.rb like so:
+Or "download RedCloth":http://rubyforge.org/frs/download.php/2852/RedCloth-3.0.2.tar.gz and simply run the install.rb like so:
ruby install.rb config
diff --git a/vendor/RedCloth-3.0.4/doc/REFERENCE b/vendor/RedCloth-3.0.3/doc/REFERENCE
similarity index 98%
rename from vendor/RedCloth-3.0.4/doc/REFERENCE
rename to vendor/RedCloth-3.0.3/doc/REFERENCE
index c7236e89..a3e5bec0 100644
--- a/vendor/RedCloth-3.0.4/doc/REFERENCE
+++ b/vendor/RedCloth-3.0.3/doc/REFERENCE
@@ -24,9 +24,9 @@
if it's found in a @pre@ or @code@ block.
- !!example "I am very serious.\n\n
----
-in: |-
-
- *** test
-
-out: |-
- *** test
----
-in: '*this is strong*'
-out: '
this is strong
'
----
-in: '*this test is strong*'
-out: '
this test is strong
'
----
-in:
__inline__
-out:
__inline__
----
-in: |-
- * @foo@
- * @bar@
- * and @x@ is also.
-out: "
\n\t
foo
\n\t\t
bar
\n\t\t
and x is also.
\n\t
"
----
-in: |-
-
-
-out: |-
-
<hello>
-
<hello>
----
-in: |
- Test of Markdown-style indented code.
-
- a = [1, 2, 3]
- a.each do |x|
- puts "test number", x,
- "and more!"
- end
-
- Paragraph 2.
-
- Paragraph 3.
-out: |-
-
Test of Markdown-style indented code.
-
-
a = [1, 2, 3]
- a.each do |x|
- puts "test number", x,
- "and more!"
- end
-
-
Paragraph 2.
-
-
Paragraph 3.
diff --git a/vendor/RedCloth-3.0.3/tests/images.yml b/vendor/RedCloth-3.0.3/tests/images.yml
deleted file mode 100644
index d097e0fb..00000000
--- a/vendor/RedCloth-3.0.3/tests/images.yml
+++ /dev/null
@@ -1,171 +0,0 @@
----
-in: This is an !image.jpg!
-out:
This is an
----
-in: This is an !image.jpg(with alt text)!
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg#a1!
-out:
This is an
----
-in: This is an !image.jpg!.
-out:
This is an .
----
-in: This is an !image.jpg(with alt text)!.
-out:
This is an .
----
-in: This is an !http://example.com/i/image.jpg!.
-out:
This is an .
----
-in: This is an !http://example.com/i/image.jpg#a1!.
-out:
This is an .
----
-in: This is not an image!!!
-out:
This is not an image!!!
----
-in: This is an !http://example.com/i/image.jpg!:#1
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:#a
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:#a1
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:#a10
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:index.html
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:index.html#1
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:index.html#a1
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:index.html#a10
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:index.html?foo=bar
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:index.html?foo=bar#1
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:index.html?foo=bar#a
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:index.html?foo=bar#a1
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:index.html?foo=bar#a10
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/#1
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/#a
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/#a1
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/#a10
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html#1
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html#a
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html#a1
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html#a10
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar#1
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar#a
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar#a1
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar#a10
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#1
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a1
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a10
-out:
This is an
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b.
-out:
This is an .
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#1.
-out:
This is an .
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a.
-out:
This is an .
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a1.
-out:
This is an .
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a10.
-out:
This is an .
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b, but this is not.
-out:
This is an , but this is not.
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#1, but this is not.
-out:
This is an , but this is not.
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a, but this is not.
-out:
This is an , but this is not.
----
-in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a1, but this is not.
-out:
This is an , but this is not.
----
-in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a10) This is not.
-out:
(This is an ) This is not.
----
-in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b) This is not.
-out:
(This is an ) This is not.
----
-in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#1) This is not.
-out:
(This is an ) This is not.
----
-in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a) This is not.
-out:
(This is an ) This is not.
----
-in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a1) This is not.
-out:
(This is an ) This is not.
----
-in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a10) This is not.
-out:
(This is an ) This is not.
diff --git a/vendor/RedCloth-3.0.3/tests/instiki.yml b/vendor/RedCloth-3.0.3/tests/instiki.yml
deleted file mode 100644
index 89b8ec6b..00000000
--- a/vendor/RedCloth-3.0.3/tests/instiki.yml
+++ /dev/null
@@ -1,39 +0,0 @@
---- # Bugs filed at http://www.instiki.org/show/BugReports
-in: |-
- _Hi, Joe Bob?, this should all be in italic!_
-out: |-
-
'
----
-in: |-
- h2. Version History
-
- * "Version
- 0.0":http://www.threewordslong.com/render-0-8-9b.patch - Early version using MD5 hashes.
- * "Version
- 0.1":http://www.threewordslong.com/chunk-0-1.patch.gz - First cut of new system. Much cleaner.
- * "Version 0.2":http://www.threewordslong.com/chunk-0-2.patch.gz - Fixed problem with "authors" page and some tests.
-out: |-
-
"
----
-in: 'The ION coding style document found at "IONCodingStyleGuide.doc":http://perforce:8081/@md=d&cd=//&c=82E@//depot/systest/system/main/pub/doc/IONCodingStyleGuide.doc?ac=22 codifies a couple of rules to ensure reasonably consistent code and documentation of libraries in ION. Test text'
-out:
The ION coding style document found at IONCodingStyleGuide.doc codifies a couple of rules to ensure reasonably consistent code and documentation of libraries in ION. Test text
diff --git a/vendor/RedCloth-3.0.3/tests/lists.yml b/vendor/RedCloth-3.0.3/tests/lists.yml
deleted file mode 100644
index cf8938f0..00000000
--- a/vendor/RedCloth-3.0.3/tests/lists.yml
+++ /dev/null
@@ -1,77 +0,0 @@
---- # Bret Pettichord, Thanks.
-in: |-
- * first line
- * second
- line
- * third line
-out: |-
-
-
first line
-
second
- line
-
third line
-
----
-in: |-
- p. start
-
- * one
- and one
- * two
- and two
- * three
-
- p. end
-out: |-
-
start
-
-
one
- and one
-
two
- and two
-
three
-
-
-
end
----
-in: |-
- Funky:
-
- * Testing
- *# number
- *##* bullet
- *# number
- *# number
- yeah number
- #* bullet
- *** okay
- ****# what
-
-
-out: |-
-
-
-# We don't do this.
-# ---
-# in: 4 < 5
-# out: 4 < 5
----
-in: |
- This is an H1
- =============
-
- This is an H2
- -------------
-out: |-
-
This is an H1
-
-
This is an H2
----
-in: |
- # This is an H1
-
- ## This is an H2
-
- ###### This is an H6
-out: |-
-
This is an H1
-
-
This is an H2
-
-
This is an H6
----
-in: |
- > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
- > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
- > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
- >
- > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
- > id sem consectetuer libero luctus adipiscing.
-out: |-
-
-
This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
- consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
- Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
-
-
Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
- id sem consectetuer libero luctus adipiscing.
-
-
----
-in: |
- > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
- consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
- Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
- >
- > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
- id sem consectetuer libero luctus adipiscing.
-out: |-
-
-
This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
- consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
- Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
-
-
Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
- id sem consectetuer libero luctus adipiscing.
-
-
----
-in: |
- > This is the first level of quoting.
- >
- > > This is nested blockquote.
- >
- > Back to the first level.
-out: |-
-
-
This is the first level of quoting.
-
-
This is nested blockquote.
-
-
-
-
-
-
Back to the first level.
-
-
----
-in: |
- > ## This is a header.
- >
- > 1. This is the first list item.
- > 2. This is the second list item.
- >
- > Here's some example code:
- >
- > return shell_exec("echo $input | $markdown_script");
-out: |-
-
-
This is a header.
-
-
-
-
1. This is the first list item.
- 2. This is the second list item.
----
-in: |
- I get 10 times more traffic from [Google] [1] than from
- [Yahoo] [2] or [MSN] [3].
-
- [1]: http://google.com/ "Google"
- [2]: http://search.yahoo.com/ "Yahoo Search"
- [3]: http://search.msn.com/ "MSN Search"
-
-out: |-
-
I get 10 times more traffic from Google than from
- Yahoo or MSN.
----
-in: |
- I get 10 times more traffic from [Google][] than from
- [Yahoo][] or [MSN][].
-
- [google]: http://google.com/ "Google"
- [yahoo]: http://search.yahoo.com/ "Yahoo Search"
- [msn]: http://search.msn.com/ "MSN Search"
-out: |-
-
I get 10 times more traffic from Google than from
- Yahoo or MSN.
diff --git a/vendor/RedCloth-3.0.3/tests/poignant.yml b/vendor/RedCloth-3.0.3/tests/poignant.yml
deleted file mode 100644
index 1a0f6942..00000000
--- a/vendor/RedCloth-3.0.3/tests/poignant.yml
+++ /dev/null
@@ -1,64 +0,0 @@
---- # Tests from the (Poignant Guide)
-in: >
- h3. False
-
-
- !
- if plastic_cup
- print "Plastic cup is on the up 'n' up!"
- end
-
-
-
- If @plastic_cup@ contains either @nil@ or @false@, you won't see anything print
- to the screen. They're not on the @if@ guest list. So @if@ isn't going to run
- any of the code it's protecting.
-
-
- But @nil@ and @false@ need not walk away in shame. They may be of questionable
- character, but @unless@ runs a smaller establishment that caters to the bedraggled.
- The @unless@ keyword has a policy of only allowing those with a negative charge in.
- Who are: @nil@ and @false@.
-
-
-
- unless plastic_cup
- print "Plastic cup is on the down low."
- end
-
-
-
- You can also use @if@ and @unless@ at the end of a single line of code, if that's
- all that is being protected.
-
-
-
- print "Yeah, plastic cup is up again!" if plastic_cup
- print "Hardly. It's down." unless plastic_cup
-
-
-
- Now that you've met @false@, I'm sure you can see what's on next.
-
-out: "
False
\n\n\t\n\n\t
The cat Trady Blix. Frozen in emptiness. Immaculate whiskers rigid. Placid eyes of lake. Tail of warm icicle. Sponsored by a Very Powerful Pause Button.
\n\n\t
The darkness surrounding Blix can be called negative space. Hang on to that phrase. Let it suggest that the emptiness has a negative connotation. In a similar way, nil has a slightly sour note that it whistles.
\n\n\t
Generally speaking, everything in Ruby has a positive charge to it. This spark flows through strings, numbers, regexps, all of it. Only two keywords wear a shady cloak: nil and false draggin us down.
\n\n\t
You can test that charge with an if keyword. It looks very much like the do blocks we saw in the last chapter, in that both end with an end.
\n\n\n
\n if plastic_cup\n print \"Plastic cup is on the up 'n' up!\" \n end\n
\n\t
If plastic_cup contains either nil or false, you won’t see anything print to the screen. They’re not on the if guest list. So if isn’t going to run any of the code it’s protecting.
\n\n\t
But nil and false need not walk away in shame. They may be of questionable character, but unless runs a smaller establishment that caters to the bedraggled. The unless keyword has a policy of only allowing those with a negative charge in. Who are: nil and false.
\n\n\n
\n unless plastic_cup\n print \"Plastic cup is on the down low.\" \n end\n
\n\t
You can also use if and unless at the end of a single line of code, if that’s all that is being protected.
\n\n\n
\n print \"Yeah, plastic cup is up again!\" if plastic_cup\n print \"Hardly. It's down.\" unless plastic_cup\n
\n\t
Now that you’ve met false, I’m sure you can see what’s on next.
"
diff --git a/vendor/RedCloth-3.0.3/tests/table.yml b/vendor/RedCloth-3.0.3/tests/table.yml
deleted file mode 100644
index bf5059e1..00000000
--- a/vendor/RedCloth-3.0.3/tests/table.yml
+++ /dev/null
@@ -1,198 +0,0 @@
-in: |
- {background:#ddd}. |S|Target|Complete|App|Milestone|
- |!/i/g.gif!|11/18/04|11/18/04|070|XML spec complete|
- |!/i/g.gif!|11/29/04|11/29/04|011|XML spec complete (KH is on schedule)|
- |!/i/g.gif!|11/29/04|11/29/04|051|XML spec complete (KH is on schedule)|
- |!/i/g.gif!|11/29/04|11/29/04|081|XML spec complete (KH is on schedule)|
- |!/i/g.gif!|11/19/04|11/22/04|070|Preprocessor complete|
- |!/i/g.gif!|11/22/04|11/22/04|070|Dialog pass 1 builds an index file|
- |!/i/g.gif!|11/24/04|11/24/04|070|Dialog pass 2 98% complete|
- |!/i/g.gif!|11/30/04|11/30/04|070|Feature complete. Passes end-to-end smoke test.|
- |!/i/g.gif!|11/30/04|11/30/04|011|Preprocessor updates complete|
- |!/i/g.gif!|11/30/04|11/30/04|051|Preprocessor updates complete|
- |!/i/g.gif!|11/30/04|11/29/04|081|Preprocessor updates complete|
- |!/i/w.gif!|12/02/04|.|011|Dialog pass 1 and 2 complete (98+%)|
- |!/i/w.gif!|12/02/04|.|051|Dialog pass 1 and 2 complete (98+%)|
- |!/i/w.gif!|12/02/04|.|081|Dialog pass 1 and 2 complete (98+%)|
- |!/i/w.gif!|12/03/04|.|011|Feature complete|
- |!/i/w.gif!|12/03/04|.|051|Feature complete|
- |!/i/w.gif!|12/03/04|.|081|Feature complete|
- |!/i/w.gif!|12/10/04|.|011|Deployed to Napa test workstation. Passes smoke test.|
- |!/i/w.gif!|12/10/04|.|051|Deployed to Napa test workstation. Passes smoke test.|
- |!/i/w.gif!|12/10/04|.|081|Deployed to Napa test workstation. Passes smoke test.|
- |!/i/w.gif!|12/10/04|.|070|Deployed to Napa test workstation. Passes smoke test.|
- |!/i/w.gif!|12/17/04|.|011|System testing complete. Begin testing with live customer data.|
- |!/i/w.gif!|12/17/04|.|051|System testing complete. Begin testing with live customer data.|
- |!/i/w.gif!|12/17/04|.|081|System testing complete. Begin testing with live customer data.|
- |!/i/w.gif!|12/17/04|.|070|System testing complete. Begin testing with live customer data.|
-out: |-
-
-
-
S
-
Target
-
Complete
-
App
-
Milestone
-
-
-
-
11/18/04
-
11/18/04
-
070
-
XML spec complete
-
-
-
-
11/29/04
-
11/29/04
-
011
-
XML spec complete (KH is on schedule)
-
-
-
-
11/29/04
-
11/29/04
-
051
-
XML spec complete (KH is on schedule)
-
-
-
-
11/29/04
-
11/29/04
-
081
-
XML spec complete (KH is on schedule)
-
-
-
-
11/19/04
-
11/22/04
-
070
-
Preprocessor complete
-
-
-
-
11/22/04
-
11/22/04
-
070
-
Dialog pass 1 builds an index file
-
-
-
-
11/24/04
-
11/24/04
-
070
-
Dialog pass 2 98% complete
-
-
-
-
11/30/04
-
11/30/04
-
070
-
Feature complete. Passes end-to-end smoke test.
-
-
-
-
11/30/04
-
11/30/04
-
011
-
Preprocessor updates complete
-
-
-
-
11/30/04
-
11/30/04
-
051
-
Preprocessor updates complete
-
-
-
-
11/30/04
-
11/29/04
-
081
-
Preprocessor updates complete
-
-
-
-
12/02/04
-
011
-
Dialog pass 1 and 2 complete (98+%)
-
-
-
-
12/02/04
-
051
-
Dialog pass 1 and 2 complete (98+%)
-
-
-
-
12/02/04
-
081
-
Dialog pass 1 and 2 complete (98+%)
-
-
-
-
12/03/04
-
011
-
Feature complete
-
-
-
-
12/03/04
-
051
-
Feature complete
-
-
-
-
12/03/04
-
081
-
Feature complete
-
-
-
-
12/10/04
-
011
-
Deployed to Napa test workstation. Passes smoke test.
-
-
-
-
12/10/04
-
051
-
Deployed to Napa test workstation. Passes smoke test.
-
-
-
-
12/10/04
-
081
-
Deployed to Napa test workstation. Passes smoke test.
-
-
-
-
12/10/04
-
070
-
Deployed to Napa test workstation. Passes smoke test.
-
-
-
-
12/17/04
-
011
-
System testing complete. Begin testing with live customer data.
-
-
-
-
12/17/04
-
051
-
System testing complete. Begin testing with live customer data.
-
-
-
-
12/17/04
-
081
-
System testing complete. Begin testing with live customer data.
-
-
-
-
12/17/04
-
070
-
System testing complete. Begin testing with live customer data.
-# ---
-# in: |-
-# This is a "link":bob to Bob's website.
-#
-# [bob]http://itsbob.com/index.html
----
-in: ACLU(American Civil Liberties Union)
-out:
ACLU
----
-in: |-
- h2{color:green}. This is a title
-
- h3. This is a subhead
-
- p{color:red}. This is some text of dubious character. Isn't the use of "quotes" just lazy writing -- and theft of 'intellectual property' besides? I think the time has come to see a block quote.
-
- bq[fr]. This is a block quote. I'll admit it's not the most exciting block quote ever devised.
-
- Simple list:
-
- #{color:blue} one
- # two
- # three
-
- Multi-level list:
-
- # one
- ## aye
- ## bee
- ## see
- # two
- ## x
- ## y
- # three
-
- Mixed list:
-
- * Point one
- * Point two
- ## Step 1
- ## Step 2
- ## Step 3
- * Point three
- ** Sub point 1
- ** Sub point 2
-
-
- Well, that went well. How about we insert an old-fashioned hypertext link? Will the quote marks in the tags get messed up? No!
-
- "This is a link (optional title)":http://www.textism.com
-
- table{border:1px solid black}.
- |_. this|_. is|_. a|_. header|
- <{background:gray}. |\2. this is|{background:red;width:200px}. a|^<>{height:200px}. row|
- |this|<>{padding:10px}. is|^. another|(bob#bob). row|
-
- An image:
-
- !/common/textist.gif(optional alt text)!
-
- # Librarians rule
- # Yes they do
- # But you knew that
-
- Some more text of dubious character. Here is a noisome string of CAPITAL letters. Here is something we want to _emphasize_.
- That was a linebreak. And something to indicate *strength*. Of course I could use my own HTML tags if I felt like it.
-
- h3. Coding
-
- This is some code, "isn't it". Watch those quote marks! Now for some preformatted text:
-
-
-
- This isn't code.
-
-
- So you see, my friends:
-
- * The time is now
- * The time is not later
- * The time is not yesterday
- * We must act
-
-out: |-
-
This is a title
-
-
This is a subhead
-
-
This is some text of dubious character. Isn’t the use of “quotes” just lazy writing—and theft of ‘intellectual property’ besides? I think the time has come to see a block quote.
-
-
-
This is a block quote. I’ll admit it’s not the most exciting block quote ever devised.
-
-
-
Simple list:
-
-
one
-
two
-
three
-
-
-
Multi-level list:
-
-
one
-
-
aye
-
bee
-
see
-
-
-
two
-
-
x
-
y
-
-
-
three
-
-
-
Mixed list:
-
-
Point one
-
Point two
-
-
Step 1
-
Step 2
-
Step 3
-
-
-
Point three
-
-
Sub point 1
-
Sub point 2
-
-
-
-
Well, that went well. How about we insert an old-fashioned hypertext link? Will the quote marks in the tags get messed up? No!
Some more text of dubious character. Here is a noisome string of CAPITAL letters. Here is something we want to emphasize.
- That was a linebreak. And something to indicate strength. Of course I could use my own HTML tags if I felt like it.
-
-
Coding
-
-
This is some code, "isn't it". Watch those quote marks! Now for some preformatted text:
-
diff --git a/vendor/rubyzip-0.5.8/ChangeLog b/vendor/rubyzip-0.5.8/ChangeLog
deleted file mode 100644
index 1bb67582..00000000
--- a/vendor/rubyzip-0.5.8/ChangeLog
+++ /dev/null
@@ -1,1273 +0,0 @@
-2005-03-17 18:11 thomas
-
- * NEWS, README, lib/zip/zip.rb: [no log message]
-
-2005-03-17 18:04 thomas
-
- * install.rb: Fixed install.rb
-
-2005-03-03 18:38 thomas
-
- * Rakefile: [no log message]
-
-2005-02-27 16:23 thomas
-
- * lib/zip/ziprequire.rb: Added documentation to ziprequire
-
-2005-02-27 16:17 thomas
-
- * README, TODO, lib/zip/ziprequire.rb: Added documentation to
- ziprequire
-
-2005-02-27 15:02 thomas
-
- * Rakefile, test/ziptest.rb: [no log message]
-
-2005-02-19 21:30 thomas
-
- * lib/zip/ioextras.rb, lib/zip/stdrubyext.rb,
- lib/zip/tempfile_bugfixed.rb, lib/zip/zip.rb,
- lib/zip/ziprequire.rb, test/ioextrastest.rb,
- test/stdrubyexttest.rb, test/zipfilesystemtest.rb,
- test/ziprequiretest.rb, test/ziptest.rb: Added more rdoc and
- changed the remaining tests to Test::Unit
-
-2005-02-19 20:28 thomas
-
- * lib/zip/: ioextras.rb, zip.rb: Added documentation to
- ZipInputStream and ZipOutputStream
-
-2005-02-18 10:27 thomas
-
- * README: [no log message]
-
-2005-02-17 23:21 thomas
-
- * README, Rakefile: Added ppackage (publish package) task to
- Rakefile
-
-2005-02-17 22:49 thomas
-
- * README, Rakefile, TODO: Added pdoc (publish doc) task to Rakefile
-
-2005-02-17 21:27 thomas
-
- * README, Rakefile, TODO, lib/zip/stdrubyext.rb, lib/zip/zip.rb,
- lib/zip/zipfilesystem.rb: Added a bunch of documentation
-
-2005-02-17 09:47 thomas
-
- * test/ziptest.rb: [no log message]
-
-2005-02-16 20:04 thomas
-
- * NEWS, README, Rakefile: Improved documentation and added rdoc
- task to Rakefile
-
-2005-02-16 19:01 thomas
-
- * NEWS, Rakefile, lib/zip/zip.rb: [no log message]
-
-2005-02-16 18:47 thomas
-
- * Rakefile, samples/example.rb, samples/example_filesystem.rb,
- samples/gtkRubyzip.rb, samples/write_simple.rb,
- samples/zipfind.rb, test/.cvsignore, test/gentestfiles.rb:
- Improvements to Rakefile
-
-2005-02-15 23:35 thomas
-
- * NEWS, TODO: [no log message]
-
-2005-02-15 23:26 thomas
-
- * Rakefile, rubyzip.gemspec: Now uses Rake to build gem
-
-2005-02-15 22:52 thomas
-
- * Rakefile: [no log message]
-
-2005-02-15 22:39 thomas
-
- * lib/zip/zip.rb, test/.cvsignore, test/ziptest.rb, NEWS: Fixed
- compatibility issue with ruby 1.8.2. Migrated test suite to
- Test::Unit
-
-2005-02-15 22:10 thomas
-
- * NEWS, lib/zip/ioextras.rb, lib/zip/stdrubyext.rb,
- lib/zip/tempfile_bugfixed.rb, lib/zip/zip.rb,
- lib/zip/zipfilesystem.rb, lib/zip/ziprequire.rb, test/.cvsignore,
- test/file1.txt, test/file1.txt.deflatedData, test/file2.txt,
- test/gentestfiles.rb, test/ioextrastest.rb,
- test/notzippedruby.rb, test/rubycode.zip, test/rubycode2.zip,
- test/stdrubyexttest.rb, test/testDirectory.bin,
- test/zipWithDirs.zip, test/zipfilesystemtest.rb,
- test/ziprequiretest.rb, test/ziptest.rb, test/data/.cvsignore,
- test/data/file1.txt, test/data/file1.txt.deflatedData,
- test/data/file2.txt, test/data/notzippedruby.rb,
- test/data/rubycode.zip, test/data/rubycode2.zip,
- test/data/testDirectory.bin, test/data/zipWithDirs.zip: Changed
- directory structure
-
-2005-02-13 22:44 thomas
-
- * Rakefile, TODO: [no log message]
-
-2005-02-13 22:38 thomas
-
- * rubyzip.gemspec: [no log message]
-
-2005-02-13 21:53 thomas
-
- * install.rb: Made install.rb independent of the current path
- (fixes bug reported by Drew Robinson)
-
-2004-12-12 11:22 thomas
-
- * NEWS, TODO, samples/write_simple.rb: Fixed 'version needed to
- extract'-field wrong in local headers
-
-2004-05-02 15:17 thomas
-
- * rubyzip.gemspec: Added gemspec contributed by Chad Fowler
-
-2004-04-02 07:25 thomas
-
- * NEWS: Fix for FreeBSD 4.9
-
-2004-03-29 00:28 thomas
-
- * NEWS: [no log message]
-
-2004-03-28 17:59 thomas
-
- * NEWS: [no log message]
-
-2004-03-27 16:09 thomas
-
- * test/stdrubyexttest.rb: Patch for stdrubyext.rb from Nobu Nakada
-
-2004-03-27 15:30 thomas
-
- * test/: ioextrastest.rb, stdrubyexttest.rb: converted some files
- to unix line-endings
-
-2004-03-25 16:34 thomas
-
- * NEWS, install.rb: Significantly reduced memory footprint when
- modifying zip files
-
-2004-03-16 18:20 thomas
-
- * install.rb, test/alltests.rb, test/ioextrastest.rb,
- test/stdrubyexttest.rb, test/ziptest.rb: IO utility classes moved
- to new file ioextras.rb. Tests moved to new file ioextrastest.rb
-
-2004-02-27 13:21 thomas
-
- * NEWS: Optimization to avoid decompression and recompression
-
-2004-01-30 16:17 thomas
-
- * NEWS: [no log message]
-
-2004-01-30 16:07 thomas
-
- * README, test/zipfilesystemtest.rb, test/ziptest.rb: Applied
- extra-field patch
-
-2003-12-13 16:57 thomas
-
- * TODO: [no log message]
-
-2003-12-10 00:25 thomas
-
- * test/ziptest.rb: (Temporary) fix to bug reported by Takashi Sano
-
-2003-08-23 09:42 thomas
-
- * test/ziptest.rb, NEWS: Fixed ZipFile.get_ouput_stream bug - data
- was never written to zip
-
-2003-08-21 16:05 thomas
-
- * install.rb: [no log message]
-
-2003-08-21 16:01 thomas
-
- * alltests.rb, stdrubyexttest.rb, zipfilesystemtest.rb,
- ziprequiretest.rb, ziptest.rb, test/alltests.rb,
- test/stdrubyexttest.rb, test/zipfilesystemtest.rb,
- test/ziprequiretest.rb, test/ziptest.rb: Moved all test ruby
- files to test/
-
-2003-08-21 15:54 thomas
-
- * NEWS, install.rb, stdrubyext.rb, stdrubyexttest.rb, zip.rb,
- zipfilesystem.rb, zipfilesystemtest.rb, ziprequire.rb,
- ziprequiretest.rb, ziptest.rb, samples/example.rb,
- samples/example_filesystem.rb, samples/gtkRubyzip.rb,
- samples/zipfind.rb: Moved all production source files to zip/ so
- they are in the same dir as when they are installed
-
-2003-08-21 15:31 thomas
-
- * NEWS, TODO, alltests.rb: [no log message]
-
-2003-08-21 15:26 thomas
-
- * filearchive.rb, filearchivetest.rb, fileutils.rb: Removed
- filearchive.rb, filearchivetest.rb and fileutils.rb
-
-2003-08-21 15:24 thomas
-
- * samples/.cvsignore, samples/example_filesystem.rb, zip.rb: Added
- samples/example_filesystem.rb. Fixed Tempfile creation for
- entries created with get_output_stream where entries were in a
- subdirectory
-
-2003-08-21 15:15 thomas
-
- * zip.rb, ziptest.rb: Fixed mkdir bug. ZipFile.mkdir didn't work if
- the zipfile doesn't exist already
-
-2003-08-21 15:05 thomas
-
- * ziptest.rb: [no log message]
-
-2003-08-21 14:53 thomas
-
- * TODO, zipfilesystemtest.rb: Globbing test placeholder commented
- out
-
-2003-08-21 14:32 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented ZipFsDir.new
- and open
-
-2003-08-21 14:19 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented DirFsIterator
- and tests
-
-2003-08-20 22:50 thomas
-
- * NEWS, TODO: [no log message]
-
-2003-08-20 22:45 thomas
-
- * zipfilesystemtest.rb: [no log message]
-
-2003-08-20 22:44 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsDir.foreach, ZipFsDir.entries now reimplemented in terms of
- it
-
-2003-08-20 22:25 thomas
-
- * README: [no log message]
-
-2003-08-20 18:08 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: [no log message]
-
-2003-08-20 17:30 thomas
-
- * zipfilesystem.rb: All access from ZipFsFile and ZipFsDir to
- ZipFile is now routed through ZipFileNameMapper which has the
- single responsibility of mapping entry/filenames
-
-2003-08-20 17:18 thomas
-
- * alltests.rb, stdrubyext.rb, stdrubyexttest.rb: Added
- stdrubyexttest.rb and added test test_select_map
-
-2003-08-20 16:10 thomas
-
- * zipfilesystem.rb: ZipFsDir was in the wrong module. ZipFileSystem
- now has a ctor that creates ZipFsDir and ZipFsFile instances,
- instead of creating them lazily. It then passes the dir instance
- to the file instance and vice versa
-
-2003-08-20 15:55 thomas
-
- * zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: ZipFsFile.open
- honours chdir
-
-2003-08-20 15:39 thomas
-
- * stdrubyext.rb, zip.rb, zipfilesystem.rb, zipfilesystemtest.rb,
- ziptest.rb: Fixed ZipEntry::parent_as_string. Implemented
- ZipFsDir.chdir, pwd and entries including test
-
-2003-08-19 15:44 thomas
-
- * zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsDir.mkdir
-
-2003-08-19 15:07 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsDir.delete (and aliases rmdir and unlink)
-
-2003-08-19 14:33 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Another dummy
- implementation and commented out a test for select() which can be
- added later
-
-2003-08-18 20:40 thomas
-
- * ziptest.rb: Honoured 1.8.0 Object.to_a deprecation warning
-
-2003-08-18 20:30 thomas
-
- * zip.rb, ziptest.rb, samples/example.rb, samples/zipfind.rb:
- Converted a few more names to ruby underscore style that I missed
- with the automated processing the first time around
-
-2003-08-18 18:39 thomas
-
- * zip.rb, zipfilesystem.rb, zipfilesystemtest.rb, ziptest.rb:
- Implemented Zip::ZipFile.get_output_stream
-
-2003-08-17 18:28 thomas
-
- * README, install.rb, stdrubyext.rb, zipfilesystem.rb,
- zipfilesystemtest.rb: Updated README with Documentation section.
- Updated install.rb. Fixed three tests that failed on 1.8.0.
-
-2003-08-14 05:40 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Added empty
- implementations of atime and ctime
-
-2003-08-13 17:08 thomas
-
- * simpledist.rb: Moved simpledist to a separate repository called
- 'misc'
-
-2003-08-13 16:31 thomas
-
- * NEWS: [no log message]
-
-2003-08-13 16:29 thomas
-
- * stdrubyext.rb, zip.rb, zipfilesystem.rb, zipfilesystemtest.rb,
- ziprequire.rb, ziprequiretest.rb, ziptest.rb, samples/example.rb,
- samples/gtkRubyzip.rb, samples/zipfind.rb: Changed all method
- names to the ruby convention underscore style
-
-2003-08-13 15:18 thomas
-
- * alltests.rb, zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- a lot more of the stat methods. Mostly with dummy implementations
- that return values that indicate that these features aren't
- supported
-
-2003-08-13 11:44 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented more methods
- and tests in zipfilesystem. Mostly empty methods as permissions
- and file types other than files and directories are not supported
-
-2003-08-13 11:29 thomas
-
- * install.rb, stdrubyext.rb, zip.rb, zipfilesystem.rb,
- zipfilesystemtest.rb: Addd file stdrubyext.rb and moved the
- modifications to std ruby classes to it. Refactored the ZipFsStat
- tests and ZipFsStat. Added Module.forwardMessages and used it to
- implement the forwarding of calls in ZipFsStat
-
-2003-08-13 10:39 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Added
- Zip::ZipFsFile::ZipFsStat and started implementing it and its
- methods
-
-2003-08-13 10:02 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb, ziptest.rb: Updated and
- added missing copyright notices
-
-2003-08-13 10:00 thomas
-
- * zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: zipfilesystem.rb
- is becoming big and not everyone will want to use that code.
- Therefore zip.rb no longer requires it. Instead you must require
- zipfilesystem.rb itself if you want to use it
-
-2003-08-13 09:51 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented dummy
- permission test methods
-
-2003-08-13 06:37 thomas
-
- * TODO, zip.rb, ziptest.rb: Merged from patch from Kristoffer
- Lunden. Fixed more 1.8.0 incompatibilites - tests run on 1.8.0
- now
-
-2003-08-12 19:18 thomas
-
- * zip.rb: Get rid of 1.8.0 warning
-
-2003-08-12 19:14 thomas
-
- * ziptest.rb: ruby 1.8.0 compatibility fix
-
-2003-08-12 19:13 thomas
-
- * NEWS, zip.rb: ruby-zlib 0.6.0 compatibility fix
-
-2002-12-22 20:12 thomas
-
- * zip.rb: [no log message]
-
-2002-09-16 22:11 thomas
-
- * NEWS: [no log message]
-
-2002-09-15 17:16 thomas
-
- * samples/zipfind.rb: [no log message]
-
-2002-09-15 00:02 thomas
-
- * samples/zipfind.rb: [no log message]
-
-2002-09-14 22:59 thomas
-
- * samples/zipfind.rb: Added simple zipfind script
-
-2002-09-13 23:53 thomas
-
- * TODO: Added TODO about openmode for zip entries binary/ascii
-
-2002-09-13 20:54 thomas
-
- * NEWS: ziptest now runs without errors with ruby-1.7.2-4 (Andy's
- latest build)
-
-2002-09-13 20:51 thomas
-
- * zip.rb, ziprequiretest.rb, ziptest.rb: ziptest now runs without
- errors with ruby-1.7.2-4 (Andy's latest build)
-
-2002-09-12 00:20 thomas
-
- * zipfilesystemtest.rb: Improved ZipFsFile.delete/unlink test
-
-2002-09-12 00:12 thomas
-
- * test/.cvsignore: [no log message]
-
-2002-09-12 00:10 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsFile.delete/unlink
-
-2002-09-11 22:22 thomas
-
- * alltests.rb: [no log message]
-
-2002-09-11 22:18 thomas
-
- * NEWS, zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: Fixed
- AbstractInputStream.each_line ignored its aSeparator argument.
- Implemented more ZipFsFile methods
-
-2002-09-11 21:28 thomas
-
- * zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: ZipFileSystem is
- now a module instead of a class, and is mixed into ZipFile,
- instead of being made available as a property fileSystem
-
-2002-09-10 23:45 thomas
-
- * NEWS: Updated NEWS file
-
-2002-09-10 23:26 thomas
-
- * zip.rb: [no log message]
-
-2002-09-10 22:39 thomas
-
- * NEWS, zip.rb, ziptest.rb: Fix bug: rewind should reset lineno.
- Fix bug: Deflater.read uses separate buffer from produceInput
- (feeding gets/readline etc)
-
-2002-09-09 23:48 thomas
-
- * .cvsignore: [no log message]
-
-2002-09-09 22:55 uid26649
-
- * zip.rb, ziptest.rb: Implemented ZipInputStream.rewind and
- AbstractInputStream.lineno. Tests for both
-
-2002-09-09 20:31 thomas
-
- * zip.rb, ziptest.rb: ZipInputStream and ZipOutstream (thru their
- AbstractInputStream and AbstractOutputStream now lie about being
- kind_of?(IO)
-
-2002-09-08 16:38 thomas
-
- * zipfilesystemtest.rb: [no log message]
-
-2002-09-08 16:07 thomas
-
- * filearchive.rb, filearchivetest.rb, zip.rb, ziptest.rb: Moved
- String additions from filearchive.rb to zip.rb (and moved tests
- along too to ziptest.rb). Added ZipEntry.parentAsString and
- ZipEntrySet.parent
-
-2002-09-08 15:28 thomas
-
- * ziptest.rb: Implemented ZipEntrySetTest.testDup and testCompound
-
-2002-09-08 15:17 thomas
-
- * TODO, zip.rb, ziptest.rb: Replaced Array with EntrySet for
- keeping entries in a zip file. Tagged repository before this
- commit, so this change can be rolled back, if it stinks
-
-2002-09-07 20:21 thomas
-
- * zip.rb, ziptest.rb: Implemented ZipEntry.<=>
-
-2002-09-07 14:48 thomas
-
- * ziptest.rb: Removed unused code
-
-2002-08-11 15:14 thomas
-
- * zip.rb, ziptest.rb: Made some changes to accomodate ruby 1.7.2
-
-2002-07-27 15:25 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented ZipFsFile.new
-
-2002-07-27 00:30 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsFile.pipe
-
-2002-07-27 00:25 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsFile.link
-
-2002-07-27 00:23 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsFile.symlink
-
-2002-07-27 00:20 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsFile.readlink, wrapped ZipFileSystem class in Zip module
-
-2002-07-27 00:14 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsFile.zero?
-
-2002-07-27 00:01 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented test for
- ZipFsFile.directory?
-
-2002-07-26 23:56 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsFile.socket?
-
-2002-07-26 23:50 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsFile.join
-
-2002-07-26 23:32 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsFile.ftype
-
-2002-07-26 23:19 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsFile.blockdev?
-
-2002-07-26 23:12 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsFile.size? (slightly different from size)
-
-2002-07-26 23:03 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsFile.split
-
-2002-07-26 23:00 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implemented
- ZipFsFile.symlink?
-
-2002-07-26 22:58 thomas
-
- * alltests.rb, zip.rb, zipfilesystem.rb, zipfilesystemtest.rb:
- Implemented ZipFsFile.mtime
-
-2002-07-26 17:08 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: Implement ZipFsFile.file?
-
-2002-07-26 17:06 thomas
-
- * zip.rb, ziptest.rb: Implemented ZipEntry.file?
-
-2002-07-26 16:57 thomas
-
- * alltests.rb, filearchive.rb, filearchivetest.rb, zip.rb,
- zipfilesystem.rb, zipfilesystemtest.rb, ziprequire.rb,
- ziptest.rb: Implemented ZipFileSystem::ZipFsFile.size
-
-2002-07-26 16:41 thomas
-
- * zipfilesystem.rb, zipfilesystemtest.rb: [no log message]
-
-2002-07-26 16:40 thomas
-
- * test/zipWithDirs.zip: Changed zipWithDirs.zip so all the entries
- in it have unix file endings
-
-2002-07-26 16:12 thomas
-
- * alltests.rb, zip.rb, zipfilesystem.rb, zipfilesystemtest.rb:
- Started implementing ZipFileSystem
-
-2002-07-26 15:56 thomas
-
- * test/zipWithDirs.zip: Added a zip file for testing with a
- directory structure
-
-2002-07-22 21:40 thomas
-
- * TODO: [no log message]
-
-2002-07-22 17:49 thomas
-
- * TODO: [no log message]
-
-2002-07-21 18:20 thomas
-
- * NEWS: [no log message]
-
-2002-07-21 18:12 thomas
-
- * TODO: Updated TODO with a refactoring idea for FileArchive
-
-2002-07-21 17:59 thomas
-
- * filearchive.rb, filearchivetest.rb: Added some FileArchiveAdd
- tests and cleaned up some of the FileArchive tests. extract and
- add now have individual test fixtures.
-
-2002-07-21 16:02 thomas
-
- * filearchive.rb, filearchivetest.rb: Added tests for extract
- called with regex src arg and Enumerable src arg
-
-2002-07-21 15:37 thomas
-
- * filearchivetest.rb: Added test for continueOnExistsProc when
- extracting from a file archive
-
-2002-07-20 17:13 thomas
-
- * TODO, filearchivetest.rb, fileutils.rb, ziptest.rb,
- test/.cvsignore: Added (failing) tests for FileArchive.add, added
- code for creating test files for FileArchive.add tests. Added
- fileutils.rb, which is borrowed from ruby 1.7.2
-
-2002-07-20 16:07 thomas
-
- * filearchive.rb, filearchivetest.rb: [no log message]
-
-2002-07-20 16:05 thomas
-
- * filearchivetest.rb: Added tests for String extensions
-
-2002-07-20 02:20 thomas
-
- * alltests.rb, ziprequiretest.rb, ziptest.rb: [no log message]
-
-2002-07-20 00:42 thomas
-
- * install.rb: [no log message]
-
-2002-07-20 00:42 thomas
-
- * TODO: Updated TODO
-
-2002-07-20 00:35 thomas
-
- * filearchive.rb, filearchivetest.rb: All FileArchive.extract tests
- run
-
-2002-07-19 23:11 thomas
-
- * filearchive.rb, filearchivetest.rb: [no log message]
-
-2002-07-19 19:41 thomas
-
- * filearchivetest.rb: [no log message]
-
-2002-07-19 19:06 thomas
-
- * filearchive.rb, filearchivetest.rb: [no log message]
-
-2002-07-19 18:48 thomas
-
- * filearchive.rb, filearchivetest.rb, zip.rb: [no log message]
-
-2002-07-08 13:41 thomas
-
- * TODO: [no log message]
-
-2002-06-11 19:47 thomas
-
- * filearchive.rb, filearchivetest.rb, zip.rb, ziptest.rb: [no log
- message]
-
-2002-05-25 00:41 thomas
-
- * simpledist.rb: Added hackish script for creating dist files
-
-2002-04-30 21:22 thomas
-
- * TODO: [no log message]
-
-2002-04-30 21:16 thomas
-
- * filearchive.rb, filearchivetest.rb: [no log message]
-
-2002-04-30 20:40 thomas
-
- * filearchive.rb, filearchivetest.rb: Improved testing and wrote
- some of the skeleton of extract. Still to do: Fix glob, so it
- returns a hashmap instead of a list. The map will need to map the
- full entry name to the last part of the name (which is only
- really interesting for recursively extracted entries, otherwise
- it is just the name). Glob.expandPathList should also output
- directories with a trailing slash, which is doesn't right now.
-
-2002-04-30 19:52 thomas
-
- * filearchive.rb, filearchivetest.rb: Implemented the first few
- tests for FileArchive
-
-2002-04-24 22:06 thomas
-
- * ziprequire.rb, ziprequiretest.rb: Appended copyright message to
- ziprequire.rb and ziprequiretest.rb
-
-2002-04-24 20:59 thomas
-
- * zip.rb: Made ZipEntry tolerate invalid dates
-
-2002-04-21 00:57 thomas
-
- * NEWS, TODO, zip.rb, ziptest.rb: Read and write entry modification
- date/time correctly
-
-2002-04-20 02:44 thomas
-
- * ziprequiretest.rb, test/rubycode2.zip: improved ZipRequireTest
-
-2002-04-20 02:39 thomas
-
- * ziprequire.rb: Made a warning go away
-
-2002-04-20 02:38 thomas
-
- * ziprequire.rb, ziprequiretest.rb, test/notzippedruby.rb,
- test/rubycode.zip: Fixed a bug in ziprequire. Added
- ziprequiretest.rb and test data files
-
-2002-04-19 22:43 thomas
-
- * zip.rb, ziptest.rb: Added recursion support to Glob module
-
-2002-04-18 21:37 thomas
-
- * NEWS, TODO, zip.rb, ziptest.rb: Added Glob module and GlobTest
- unit test suite. This module provides the functionality to expand
- a 'glob pattern' given a list of files - Next step is to use this
- module in ZipFile
-
-2002-04-01 22:55 thomas
-
- * NEWS: [no log message]
-
-2002-04-01 21:16 thomas
-
- * TODO, zip.rb, ziprequire.rb: Added ziprequire.rb which contains a
- proof-of-concept implementation of a require implementation that
- can load ruby modules from a zip file. Needs unit tests and
- polish.
-
-2002-03-31 01:13 thomas
-
- * README: [no log message]
-
-2002-03-30 16:14 thomas
-
- * TODO: [no log message]
-
-2002-03-30 01:52 thomas
-
- * .cvsignore, README, zip.rb: Added rdoc markup (only #:nodoc:all
- modifiers) to zip.rb. Made README 'RDoc compliant'
-
-2002-03-29 23:29 thomas
-
- * TODO: [no log message]
-
-2002-03-29 23:26 thomas
-
- * example.rb, samples/.cvsignore, samples/example.rb,
- samples/gtkRubyzip.rb: Moved example.rb to samples/. Added
- another sample gtkRubyzip.rb
-
-2002-03-29 20:12 thomas
-
- * NEWS, TODO: [no log message]
-
-2002-03-29 20:06 thomas
-
- * .cvsignore, file1.txt, file1.txt.deflatedData, testDirectory.bin,
- ziptest.rb, test/.cvsignore, test/file1.txt,
- test/file1.txt.deflatedData, test/file2.txt,
- test/testDirectory.bin: Added test/ directory and moved the
- manually created test data files into it. Changed ziptest.rb so
- it runs in test/ directory
-
-2002-03-29 19:43 thomas
-
- * TODO: [no log message]
-
-2002-03-29 18:15 thomas
-
- * NEWS, zip.rb, ziptest.rb: Don't decompress and recompress zip
- entries when changing zip file
-
-2002-03-29 17:50 thomas
-
- * zip.rb: Performance optimization: Only write new ZipFile, if it
- has been changed. The test suite runs in half the time now.
-
-2002-03-28 22:12 thomas
-
- * TODO: [no log message]
-
-2002-03-23 17:31 thomas
-
- * TODO: [no log message]
-
-2002-03-22 22:47 thomas
-
- * NEWS: [no log message]
-
-2002-03-22 22:25 thomas
-
- * NEWS, TODO: [no log message]
-
-2002-03-22 22:18 thomas
-
- * ziptest.rb: Found the tests that didn't use blocks to make sure
- input streams are closed as soon as they arent used anymore and
- got rid of the GC.start
-
-2002-03-22 22:12 thomas
-
- * ziptest.rb: All tests run on windows ruby 1.6.6
-
-2002-03-22 10:38 thomas
-
- * zip.rb, ziptest.rb: Windows fixes: Fixed ZipFile.initialize which
- needed to open zipfile file in binary mode. Added another
- workaround for the return value from File.open(name) where name
- is the name of a directory - ruby returns different exceptions in
- linux, win/cygwin and windows. A number of tests failed because
- in windows you cant delete a file that is open. Fixed by changing
- ziptest.rb to use ZipInputStream.getInputStream with blocks a few
- places. There is a hack in CommanZipFileFixture.setup where the
- GC is explicitly invoked. Should be fixed with blocks instead.
- The only currently failing test fails because the test data
- creation fails to add a comment to 4entry.zip, because echo eats
- the remainder of the line including the pipe character and the
- following zip -z 4 entry.zip command
-
-2002-03-21 22:18 thomas
-
- * NEWS: [no log message]
-
-2002-03-21 22:12 thomas
-
- * NEWS, README, TODO, install.rb: Added install.rb
-
-2002-03-21 21:45 thomas
-
- * ziptest.rb: [no log message]
-
-2002-03-21 20:54 thomas
-
- * NEWS, TODO: [no log message]
-
-2002-03-21 20:34 thomas
-
- * .cvsignore, TODO, zip.rb, ziptest.rb: Added
- test_extractDirectoryExistsAsFileOverwrite and fixed to pass
-
-2002-03-21 20:22 thomas
-
- * zip.rb, ziptest.rb: Extraction of directory entries is now
- supported
-
-2002-03-20 21:59 thomas
-
- * NEWS: [no log message]
-
-2002-03-20 21:24 thomas
-
- * COPYING, README, README.txt: Removed COPYING, renamed README.txt
- to README. Updated README
-
-2002-03-20 21:18 thomas
-
- * example.rb: Fixed example.rb added example that shows zip file
- manipulation with Zip::ZipFile
-
-2002-03-20 21:00 thomas
-
- * .cvsignore: [no log message]
-
-2002-03-20 20:56 thomas
-
- * TODO, zip.rb, ziptest.rb: Directories can now be added (not
- recursively, the directory entry itself. Directories are
- recognized by a empty entries with a trailing /. The purpose of
- storing them explicitly in the zip file is to be able to store
- permission and ownership information
-
-2002-03-20 20:08 thomas
-
- * TODO, zip.rb, ziptest.rb: zip.rb depended on ftools but it was
- only included in ziptest.rb
-
-2002-03-20 19:07 thomas
-
- * zip.rb, ziptest.rb: ZipError is now a subclass of StandardError
- instead of RuntimeError. ZipError now has several subclasses.
-
-2002-03-19 22:26 thomas
-
- * TODO: [no log message]
-
-2002-03-19 22:19 thomas
-
- * TODO, ziptest.rb: Unit test ZipFile.getInputStream with block
-
-2002-03-19 22:11 thomas
-
- * TODO, zip.rb, ziptest.rb: Unit test for adding new entry with
- name that already exists in archive, and fixed to pass test
-
-2002-03-19 21:40 thomas
-
- * TODO, zip.rb, ziptest.rb: Added unit tests for rename to existing
- entry
-
-2002-03-19 20:42 thomas
-
- * TODO: [no log message]
-
-2002-03-19 20:40 thomas
-
- * TODO, zip.rb, ziptest.rb: Unit test calling ZipFile.extract with
- block
-
-2002-03-18 21:06 thomas
-
- * TODO: [no log message]
-
-2002-03-18 21:05 thomas
-
- * zip.rb, ziptest.rb: ZipFile#commit now reinitializes ZipFile.
-
-2002-03-18 20:42 thomas
-
- * TODO, zip.rb, ziptest.rb: Refactoring:
-
- Collapsed ZipEntry and ZipStreamableZipEntry into ZipEntry.
-
- Collapsed BasicZipFile and ZipFile into ZipFile.
-
-2002-03-18 18:05 thomas
-
- * zip.rb: Removed method that was never called
-
-2002-03-17 22:33 thomas
-
- * TODO: [no log message]
-
-2002-03-17 22:25 thomas
-
- * ziptest.rb: Run tests with =true as default
-
-2002-03-17 22:22 thomas
-
- * NEWS, TODO, zip.rb, ziptest.rb: Now runs with -w switch without
- warnings
-
-2002-03-17 21:10 thomas
-
- * .cvsignore: [no log message]
-
-2002-03-17 21:04 thomas
-
- * zip.rb, ziptest.rb: Down to one failing test
-
-2002-03-17 20:36 thomas
-
- * zip.rb, ziptest.rb: [no log message]
-
-2002-03-17 17:22 thomas
-
- * TODO, zip.rb, ziptest.rb: [no log message]
-
-2002-02-25 19:42 thomas
-
- * TODO: Added more todos
-
-2002-02-23 15:51 thomas
-
- * zip.rb: [no log message]
-
-2002-02-23 15:30 thomas
-
- * zip.rb, ziptest.rb: [no log message]
-
-2002-02-23 14:16 thomas
-
- * zip.rb, ziptest.rb: [no log message]
-
-2002-02-03 18:47 thomas
-
- * ziptest.rb: [no log message]
-
-2002-02-02 15:58 thomas
-
- * example.rb, zip.rb, ziptest.rb: [no log message]
-
-2002-02-02 00:16 thomas
-
- * .cvsignore: [no log message]
-
-2002-02-02 00:14 thomas
-
- * example.rb, zip.rb, ziptest.rb: Renamed SimpleZipFile to
- BasicZipFile
-
-2002-02-02 00:09 thomas
-
- * TODO: [no log message]
-
-2002-02-02 00:01 thomas
-
- * ziptest.rb: More test cases - all of them failing, so now there
- are 18 failing test cases. Three more test cases to implement,
- then it is time for the production code
-
-2002-02-01 21:49 thomas
-
- * ziptest.rb: [no log message]
-
-2002-02-01 21:34 thomas
-
- * ziptest.rb: Also run SimpleZipFile tests for ZipFile.
-
-2002-02-01 20:11 thomas
-
- * example.rb, zip.rb, ziptest.rb: ZipFile renamed to SimpleZipFile.
- The new ZipFile will have many more methods that are useful for
- managing archives.
-
-2002-01-29 20:30 thomas
-
- * TODO: [no log message]
-
-2002-01-26 00:18 thomas
-
- * NEWS: [no log message]
-
-2002-01-26 00:14 thomas
-
- * ziptest.rb: In unit test: work around ruby/cygwin weirdness. You
- get an Errno::EEXISTS instead of an Errno::EISDIR if you try to
- open a file for writing that is a directory.
-
-2002-01-26 00:02 thomas
-
- * ziptest.rb: Fixed test that failed on windows because of CRLF
- line ending
-
-2002-01-25 23:58 thomas
-
- * ziptest.rb: [no log message]
-
-2002-01-25 23:29 thomas
-
- * .cvsignore, example.rb, zip.rb: Fixed bug reading from empty
- deflated entry in zip file
-
-2002-01-25 23:01 thomas
-
- * .cvsignore: [no log message]
-
-2002-01-25 22:56 thomas
-
- * ziptest.rb: [no log message]
-
-2002-01-25 22:51 thomas
-
- * NEWS, README.txt, zip.rb, ziptest.rb: Zip write support is now
- fully functional in the form of ZipOutputStream.
-
-2002-01-25 21:12 thomas
-
- * zip.rb, ziptest.rb: [no log message]
-
-2002-01-25 20:37 thomas
-
- * zip.rb, ziptest.rb: [no log message]
-
-2002-01-20 16:00 thomas
-
- * zip.rb, ziptest.rb: Added Deflater and DeflaterTest.
-
-2002-01-20 00:39 thomas
-
- * .cvsignore: [no log message]
-
-2002-01-20 00:23 thomas
-
- * .cvsignore: Added .cvsignore file
-
-2002-01-20 00:09 thomas
-
- * zip.rb, ziptest.rb: Added ZipEntry.writeCDirEntry and misc minor
- fixes
-
-2002-01-19 23:28 thomas
-
- * example.rb, zip.rb, ziptest.rb: NOTICE: Not all tests run!!
-
- ZipOutputStream in progress
-
- Wrapped rubyzip in namespace module Zip.
-
-2002-01-17 18:52 thomas
-
- * ziptest.rb: Fail nicely if the user doesn't have info-zip
- compatible zip in the path
-
-2002-01-10 18:02 thomas
-
- * zip.rb: Adjusted chunk size to 32k after a few perf measurements
-
-2002-01-09 22:10 thomas
-
- * README.txt: License now same as rubys, not just GPL
-
-2002-01-06 00:19 thomas
-
- * README.txt: [no log message]
-
-2002-01-05 23:09 thomas
-
- * NEWS, README.txt: Updated NEWS file
-
-2002-01-05 23:05 thomas
-
- * README.txt, zip.rb, ziptest.rb, zlib.c.diff: Added tests for
- decompressors and a tests for ZipLocalEntry,
- ZipCentralDirectoryEntry and ZipCentralDirectory for handling of
- corrupt data
-
-2002-01-05 22:21 thomas
-
- * file1.txt.deflatedData: deflated data extracted from a zip file.
- contains file1.txt
-
-2002-01-05 20:05 thomas
-
- * zip.rb: Changed references to Inflate to Zlib::inflate for
- compatibility with ruby-zlib-0.5
-
-2002-01-05 19:28 thomas
-
- * README.txt, zip.rb, ziptest.rb: [no log message]
-
-2002-01-05 01:52 thomas
-
- * example.rb, NEWS: [no log message]
-
-2002-01-05 01:37 thomas
-
- * COPYING, README.txt: [no log message]
-
-2002-01-05 01:31 thomas
-
- * ziptest.rb: Fixed problem with test file creation
-
-2002-01-05 01:15 thomas
-
- * README.txt: Updated README.txt
-
-2002-01-05 01:13 thomas
-
- * zip.rb, ziptest.rb: ZipFile now works
-
-2002-01-04 21:51 thomas
-
- * testDirectory.bin, zip.rb, ziptest.rb:
- ZipCentralDirectoryEntryTest now runs
-
-2002-01-04 18:40 thomas
-
- * ziptest.rb: Changed
- ZIpLocalNEtryTest::test_ReadLocalEntryHeaderOfFirstTestZipEntry
- so it works on both unix too. It only worked on windows because
- the test made assumptions about the compressed size and crc of an
- entry, but that differs depending on the OS because of the CRLF
- thing.
-
-2002-01-04 18:37 thomas
-
- * README.txt: Added note about zlib.c patch
-
-2002-01-02 18:48 thomas
-
- * README.txt, example.rb, file1.txt, zip.rb, ziptest.rb,
- zlib.c.diff: Initial revision
-
-2002-01-02 18:48 thomas
-
- * README.txt, example.rb, file1.txt, zip.rb, ziptest.rb,
- zlib.c.diff: initial
-
diff --git a/vendor/rubyzip-0.5.8/NEWS b/vendor/rubyzip-0.5.8/NEWS
deleted file mode 100644
index 37911fdb..00000000
--- a/vendor/rubyzip-0.5.8/NEWS
+++ /dev/null
@@ -1,110 +0,0 @@
-= Version 0.5.8
-
-Fixed install script.
-
-= Version 0.5.7
-
-install.rb no longer assumes it is being run from the toplevel source
-dir. Directory structure changed to reflect common ruby library
-project structure. Migrated from RubyUnit to Test::Unit format. Now
-uses Rake to build source packages and gems and run unit tests.
-
-= Version 0.5.6
-
-Fix for FreeBSD 4.9 which returns Errno::EFBIG instead of
-Errno::EINVAL for some invalid seeks. Fixed 'version needed to
-extract'-field incorrect in local headers.
-
-= Version 0.5.5
-
-Fix for a problem with writing zip files that concerns only ruby 1.8.1.
-
-= Version 0.5.4
-
-Significantly reduced memory footprint when modifying zip files.
-
-= Version 0.5.3
-
-Added optimization to avoid decompressing and recompressing individual
-entries when modifying a zip archive.
-
-= Version 0.5.2
-
-Fixed ZipFile corruption bug in ZipFile class. Added basic unix
-extra-field support.
-
-= Version 0.5.1
-
-Fixed ZipFile.get_output_stream bug.
-
-= Version 0.5.0
-
-List of changes:
-* Ruby 1.8.0 and ruby-zlib 0.6.0 compatibility
-* Changed method names from camelCase to rubys underscore style.
-* Installs to zip/ subdir instead of directly to site_ruby
-* Added ZipFile.directory and ZipFile.file - each method return an
-object that can be used like Dir and File only for the contents of the
-zip file.
-* Added sample application zipfind which works like Find.find, only
-Zip::ZipFind.find traverses into zip archives too.
-
-Bug fixes:
-* AbstractInputStream.each_line with non-default separator
-
-
-= Version 0.5.0a
-
-Source reorganized. Added ziprequire, which can be used to load ruby
-modules from a zip file, in a fashion similar to jar files in
-Java. Added gtkRubyzip, another sample application. Implemented
-ZipInputStream.lineno and ZipInputStream.rewind
-
-Bug fixes:
-
-* Read and write date and time information correctly for zip entries.
-* Fixed read() using separate buffer, causing mix of gets/readline/read to
-cause problems.
-
-= Version 0.4.2
-
-Performance optimizations. Test suite runs in half the time.
-
-= Version 0.4.1
-
-Windows compatibility fixes.
-
-= Version 0.4.0
-
-Zip::ZipFile is now mutable and provides a more convenient way of
-modifying zip archives than Zip::ZipOutputStream. Operations for
-adding, extracting, renaming, replacing and removing entries to zip
-archives are now available.
-
-Runs without warnings with -w switch.
-
-Install script install.rb added.
-
-
-= Version 0.3.1
-
-Rudimentary support for writing zip archives.
-
-
-= Version 0.2.2
-
-Fixed and extended unit test suite. Updated to work with ruby/zlib
-0.5. It doesn't work with earlier versions of ruby/zlib.
-
-
-= Version 0.2.0
-
-Class ZipFile added. Where ZipInputStream is used to read the
-individual entries in a zip file, ZipFile reads the central directory
-in the zip archive, so you can get to any entry in the zip archive
-without having to skipping through all the preceeding entries.
-
-
-= Version 0.1.0
-
-First working version of ZipInputStream.
diff --git a/vendor/rubyzip-0.5.8/README b/vendor/rubyzip-0.5.8/README
deleted file mode 100644
index 6ed15a92..00000000
--- a/vendor/rubyzip-0.5.8/README
+++ /dev/null
@@ -1,70 +0,0 @@
-= rubyzip
-
-rubyzip is a ruby library for reading and writing zip files.
-
-= Install
-
-If you have rubygems you can install rubyzip directly from the gem
-repository
-
- gem install rubyzip
-
-Otherwise obtain the source (see below) and run
-
- ruby install.rb
-
-To run the unit tests you need to have test::unit installed
-
- rake test
-
-
-= Documentation
-
-There is more than one way to access or create a zip archive with
-rubyzip. The basic API is modeled after the classes in
-java.util.zip from the Java SDK. This means there are classes such
-as Zip::ZipInputStream, Zip::ZipOutputStream and
-Zip::ZipFile. Zip::ZipInputStream provides a basic interface for
-iterating through the entries in a zip archive and reading from the
-entries in the same way as from a regular File or IO
-object. ZipOutputStream is the corresponding basic output
-facility. Zip::ZipFile provides a mean for accessing the archives
-central directory and provides means for accessing any entry without
-having to iterate through the archive. Unlike Java's
-java.util.zip.ZipFile rubyzip's Zip::ZipFile is mutable, which means
-it can be used to change zip files as well.
-
-Another way to access a zip archive with rubyzip is to use rubyzip's
-Zip::ZipFileSystem API. Using this API files can be read from and
-written to the archive in much the same manner as ruby's builtin
-classes allows files to be read from and written to the file system.
-
-rubyzip also features the
-zip/ziprequire.rb[link:files/lib/zip/ziprequire_rb.html] module which
-allows ruby to load ruby modules from zip archives.
-
-For details about the specific behaviour of classes and methods refer
-to the test suite. Finally you can generate the rdoc documentation or
-visit http://rubyzip.sourceforge.net.
-
-= License
-
-rubyzip is distributed under the same license as ruby. See
-http://www.ruby-lang.org/en/LICENSE.txt
-
-
-= Website and Project Home
-
-http://rubyzip.sourceforge.net
-
-http://sourceforge.net/projects/rubyzip
-
-== Download (tarballs and gems)
-
-http://sourceforge.net/project/showfiles.php?group_id=43107&package_id=35377
-
-= Authors
-
-Thomas Sondergaard (thomas at sondergaard.cc)
-
-extra-field support contributed by Tatsuki Sugiura (sugi at nemui.org)
diff --git a/vendor/rubyzip-0.5.8/Rakefile b/vendor/rubyzip-0.5.8/Rakefile
deleted file mode 100644
index 03b65c2d..00000000
--- a/vendor/rubyzip-0.5.8/Rakefile
+++ /dev/null
@@ -1,110 +0,0 @@
-# Rakefile for RubyGems -*- ruby -*-
-
-require 'rubygems'
-require 'rake/clean'
-require 'rake/testtask'
-require 'rake/packagetask'
-require 'rake/gempackagetask'
-require 'rake/rdoctask'
-require 'rake/contrib/sshpublisher'
-require 'net/ftp'
-
-PKG_NAME = 'rubyzip'
-PKG_VERSION = File.read('lib/zip/zip.rb').match(/\s+VERSION\s*=\s*'(.*)'/)[1]
-
-PKG_FILES = FileList.new
-
-PKG_FILES.add %w{ README NEWS TODO ChangeLog install.rb Rakefile }
-PKG_FILES.add %w{ samples/*.rb }
-PKG_FILES.add %w{ test/*.rb }
-PKG_FILES.add %w{ test/data/* }
-PKG_FILES.exclude "test/data/generated"
-PKG_FILES.add %w{ lib/**/*.rb }
-
-def clobberFromCvsIgnore(path)
- CLOBBER.add File.readlines(path+'/.cvsignore').map {
- |f| File.join(path, f.chomp)
- }
-end
-
-clobberFromCvsIgnore '.'
-clobberFromCvsIgnore 'samples'
-clobberFromCvsIgnore 'test'
-clobberFromCvsIgnore 'test/data'
-
-task :default => [:test]
-
-desc "Run unit tests"
-task :test do
- ruby %{-C test alltests.rb}
-end
-
-# Shortcuts for test targets
-task :ut => [:test]
-
-spec = Gem::Specification.new do |s|
- s.name = PKG_NAME
- s.version = PKG_VERSION
- s.author = "Thomas Sondergaard"
- s.email = "thomas(at)sondergaard.cc"
- s.homepage = "http://rubyzip.sourceforge.net/"
- s.platform = Gem::Platform::RUBY
- s.summary = "rubyzip is a ruby module for reading and writing zip files"
- s.files = PKG_FILES.to_a #Dir.glob("{samples,lib,test,docs}/**/*").delete_if {|item| item.include?("CVS") || item.include?("rdoc") || item =~ /~$/ }
- s.require_path = 'lib'
- s.autorequire = 'zip/zip'
-end
-
-Rake::GemPackageTask.new(spec) do |pkg|
- pkg.need_zip = true
- pkg.need_tar = true
-end
-
-Rake::RDocTask.new do |rd|
- rd.main = "README"
- rd.rdoc_files.add %W{ lib/zip/*.rb README NEWS TODO ChangeLog }
- rd.options << "--title 'rubyzip documentation' --webcvs http://cvs.sourceforge.net/viewcvs.py/rubyzip/rubyzip/"
-# rd.options << "--all"
-end
-
-desc "Publish documentation"
-task :pdoc => [:rdoc] do
- Rake::SshFreshDirPublisher.
- new("thomas@rubyzip.sourceforge.net", "rubyzip/htdocs", "html").upload
-end
-
-desc "Publish package"
-task :ppackage => [:package] do
- Net::FTP.open("upload.sourceforge.net",
- "ftp",
- ENV['USER']+"@"+ENV['HOSTNAME']) {
- |ftpclient|
- ftpclient.chdir "incoming"
- Dir['pkg/*.{tgz,zip,gem}'].each {
- |e|
- ftpclient.putbinaryfile(e, File.basename(e))
- }
- }
-end
-
-desc "Generate the ChangeLog file"
-task :ChangeLog do
- puts "Updating ChangeLog"
- system %{cvs2cl}
-end
-
-desc "Make a release"
-task :release => [:tag_release, :pdoc, :ppackage] do
-end
-
-desc "Make a release tag"
-task :tag_release do
- tag = "release-#{PKG_VERSION.gsub('.','-')}"
-
- puts "Checking for tag '#{tag}'"
- if (Regexp.new("^\\s+#{tag}") =~ `cvs log README`)
- abort "Tag '#{tag}' already exists"
- end
- puts "Tagging module with '#{tag}'"
- system("cvs tag #{tag}")
-end
diff --git a/vendor/rubyzip-0.5.8/TODO b/vendor/rubyzip-0.5.8/TODO
deleted file mode 100644
index 457298c6..00000000
--- a/vendor/rubyzip-0.5.8/TODO
+++ /dev/null
@@ -1,9 +0,0 @@
-
-* Fix problem with mixing AbstractInputStream::gets and AbstractInputStream::read
-* Implement ZipFsDir.glob
-* ZipFile.checkIntegrity method
-* non-MSDOS permission attributes
-** See mail from Ned Konz to ruby-talk subj. "Re: SV: [ANN] Archive 0.2"
-* Packager version, required unpacker version in zip headers
-** See mail from Ned Konz to ruby-talk subj. "Re: SV: [ANN] Archive 0.2"
-* implement storing attributes and ownership information
diff --git a/vendor/rubyzip-0.5.8/install.rb b/vendor/rubyzip-0.5.8/install.rb
deleted file mode 100644
index 405e2b0b..00000000
--- a/vendor/rubyzip-0.5.8/install.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env ruby
-
-$VERBOSE = true
-
-require 'rbconfig'
-require 'find'
-require 'ftools'
-
-include Config
-
-files = %w{ stdrubyext.rb ioextras.rb zip.rb zipfilesystem.rb ziprequire.rb tempfile_bugfixed.rb }
-
-INSTALL_DIR = File.join(CONFIG["sitelibdir"], "zip")
-File.makedirs(INSTALL_DIR)
-
-SOURCE_DIR = File.join(File.dirname($0), "lib/zip")
-
-files.each {
- |filename|
- installPath = File.join(INSTALL_DIR, filename)
- File::install(File.join(SOURCE_DIR, filename), installPath, 0644, true)
-}
diff --git a/vendor/rubyzip-0.5.8/samples/example.rb b/vendor/rubyzip-0.5.8/samples/example.rb
deleted file mode 100644
index 741afa76..00000000
--- a/vendor/rubyzip-0.5.8/samples/example.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/usr/bin/env ruby
-
-$: << "../lib"
-system("zip example.zip example.rb gtkRubyzip.rb")
-
-require 'zip/zip'
-
-####### Using ZipInputStream alone: #######
-
-Zip::ZipInputStream.open("example.zip") {
- |zis|
- entry = zis.get_next_entry
- print "First line of '#{entry.name} (#{entry.size} bytes): "
- puts "'#{zis.gets.chomp}'"
- entry = zis.get_next_entry
- print "First line of '#{entry.name} (#{entry.size} bytes): "
- puts "'#{zis.gets.chomp}'"
-}
-
-
-####### Using ZipFile to read the directory of a zip file: #######
-
-zf = Zip::ZipFile.new("example.zip")
-zf.each_with_index {
- |entry, index|
-
- puts "entry #{index} is #{entry.name}, size = #{entry.size}, compressed size = #{entry.compressed_size}"
- # use zf.get_input_stream(entry) to get a ZipInputStream for the entry
- # entry can be the ZipEntry object or any object which has a to_s method that
- # returns the name of the entry.
-}
-
-
-####### Using ZipOutputStream to write a zip file: #######
-
-Zip::ZipOutputStream.open("exampleout.zip") {
- |zos|
- zos.put_next_entry("the first little entry")
- zos.puts "Hello hello hello hello hello hello hello hello hello"
-
- zos.put_next_entry("the second little entry")
- zos.puts "Hello again"
-
- # Use rubyzip or your zip client of choice to verify
- # the contents of exampleout.zip
-}
-
-####### Using ZipFile to change a zip file: #######
-
-Zip::ZipFile.open("exampleout.zip") {
- |zf|
- zf.add("thisFile.rb", "example.rb")
- zf.rename("thisFile.rb", "ILikeThisName.rb")
- zf.add("Again", "example.rb")
-}
-
-# Lets check
-Zip::ZipFile.open("exampleout.zip") {
- |zf|
- puts "Changed zip file contains: #{zf.entries.join(', ')}"
- zf.remove("Again")
- puts "Without 'Again': #{zf.entries.join(', ')}"
-}
-
-# For other examples, look at zip.rb and ziptest.rb
-
-# Copyright (C) 2002 Thomas Sondergaard
-# rubyzip is free software; you can redistribute it and/or
-# modify it under the terms of the ruby license.
diff --git a/vendor/rubyzip-0.5.8/samples/example_filesystem.rb b/vendor/rubyzip-0.5.8/samples/example_filesystem.rb
deleted file mode 100644
index 867e8d4f..00000000
--- a/vendor/rubyzip-0.5.8/samples/example_filesystem.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env ruby
-
-$: << "../lib"
-
-require 'zip/zipfilesystem'
-require 'ftools'
-
-EXAMPLE_ZIP = "filesystem.zip"
-
-File.delete(EXAMPLE_ZIP) if File.exists?(EXAMPLE_ZIP)
-
-Zip::ZipFile.open(EXAMPLE_ZIP, Zip::ZipFile::CREATE) {
- |zf|
- zf.file.open("file1.txt", "w") { |os| os.write "first file1.txt" }
- zf.dir.mkdir("dir1")
- zf.dir.chdir("dir1")
- zf.file.open("file1.txt", "w") { |os| os.write "second file1.txt" }
- puts zf.file.read("file1.txt")
- puts zf.file.read("../file1.txt")
- zf.dir.chdir("..")
- zf.file.open("file2.txt", "w") { |os| os.write "first file2.txt" }
- puts "Entries: #{zf.entries.join(', ')}"
-}
-
-Zip::ZipFile.open(EXAMPLE_ZIP) {
- |zf|
- puts "Entries from reloaded zip: #{zf.entries.join(', ')}"
-}
-
-# For other examples, look at zip.rb and ziptest.rb
-
-# Copyright (C) 2003 Thomas Sondergaard
-# rubyzip is free software; you can redistribute it and/or
-# modify it under the terms of the ruby license.
diff --git a/vendor/rubyzip-0.5.8/samples/gtkRubyzip.rb b/vendor/rubyzip-0.5.8/samples/gtkRubyzip.rb
deleted file mode 100644
index 5d91829d..00000000
--- a/vendor/rubyzip-0.5.8/samples/gtkRubyzip.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/usr/bin/env ruby
-
-$: << "../lib"
-
-$VERBOSE = true
-
-require 'gtk'
-require 'zip/zip'
-
-class MainApp < Gtk::Window
- def initialize
- super()
- set_usize(400, 256)
- set_title("rubyzip")
- signal_connect(Gtk::Window::SIGNAL_DESTROY) { Gtk.main_quit }
-
- box = Gtk::VBox.new(false, 0)
- add(box)
-
- @zipfile = nil
- @buttonPanel = ButtonPanel.new
- @buttonPanel.openButton.signal_connect(Gtk::Button::SIGNAL_CLICKED) {
- show_file_selector
- }
- @buttonPanel.extractButton.signal_connect(Gtk::Button::SIGNAL_CLICKED) {
- puts "Not implemented!"
- }
- box.pack_start(@buttonPanel, false, false, 0)
-
- sw = Gtk::ScrolledWindow.new
- sw.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
- box.pack_start(sw, true, true, 0)
-
- @clist = Gtk::CList.new(["Name", "Size", "Compression"])
- @clist.set_selection_mode(Gtk::SELECTION_BROWSE)
- @clist.set_column_width(0, 120)
- @clist.set_column_width(1, 120)
- @clist.signal_connect(Gtk::CList::SIGNAL_SELECT_ROW) {
- |w, row, column, event|
- @selected_row = row
- }
- sw.add(@clist)
- end
-
- class ButtonPanel < Gtk::HButtonBox
- attr_reader :openButton, :extractButton
- def initialize
- super
- set_layout(Gtk::BUTTONBOX_START)
- set_spacing(0)
- @openButton = Gtk::Button.new("Open archive")
- @extractButton = Gtk::Button.new("Extract entry")
- pack_start(@openButton)
- pack_start(@extractButton)
- end
- end
-
- def show_file_selector
- @fileSelector = Gtk::FileSelection.new("Open zip file")
- @fileSelector.show
- @fileSelector.ok_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) {
- open_zip(@fileSelector.filename)
- @fileSelector.destroy
- }
- @fileSelector.cancel_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) {
- @fileSelector.destroy
- }
- end
-
- def open_zip(filename)
- @zipfile = Zip::ZipFile.open(filename)
- @clist.clear
- @zipfile.each {
- |entry|
- @clist.append([ entry.name,
- entry.size.to_s,
- (100.0*entry.compressedSize/entry.size).to_s+"%" ])
- }
- end
-end
-
-mainApp = MainApp.new()
-
-mainApp.show_all
-
-Gtk.main
diff --git a/vendor/rubyzip-0.5.8/samples/write_simple.rb b/vendor/rubyzip-0.5.8/samples/write_simple.rb
deleted file mode 100644
index 648989a2..00000000
--- a/vendor/rubyzip-0.5.8/samples/write_simple.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/env ruby
-
-$: << "../lib"
-
-require 'zip/zip'
-
-include Zip
-
-ZipOutputStream.open('simple.zip') {
- |zos|
- ze = zos.put_next_entry 'entry.txt'
- zos.puts "Hello world"
-}
diff --git a/vendor/rubyzip-0.5.8/samples/zipfind.rb b/vendor/rubyzip-0.5.8/samples/zipfind.rb
deleted file mode 100644
index 54ad936e..00000000
--- a/vendor/rubyzip-0.5.8/samples/zipfind.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/env ruby
-
-$VERBOSE = true
-
-$: << "../lib"
-
-require 'zip/zip'
-require 'find'
-
-module Zip
- module ZipFind
- def self.find(path, zipFilePattern = /\.zip$/i)
- Find.find(path) {
- |fileName|
- yield(fileName)
- if zipFilePattern.match(fileName) && File.file?(fileName)
- begin
- Zip::ZipFile.foreach(fileName) {
- |zipEntry|
- yield(fileName + File::SEPARATOR + zipEntry.to_s)
- }
- rescue Errno::EACCES => ex
- puts ex
- end
- end
- }
- end
-
- def self.find_file(path, fileNamePattern, zipFilePattern = /\.zip$/i)
- self.find(path, zipFilePattern) {
- |fileName|
- yield(fileName) if fileNamePattern.match(fileName)
- }
- end
-
- end
-end
-
-if __FILE__ == $0
- module ZipFindConsoleRunner
-
- PATH_ARG_INDEX = 0;
- FILENAME_PATTERN_ARG_INDEX = 1;
- ZIPFILE_PATTERN_ARG_INDEX = 2;
-
- def self.run(args)
- check_args(args)
- Zip::ZipFind.find_file(args[PATH_ARG_INDEX],
- args[FILENAME_PATTERN_ARG_INDEX],
- args[ZIPFILE_PATTERN_ARG_INDEX]) {
- |fileName|
- report_entry_found fileName
- }
- end
-
- def self.check_args(args)
- if (args.size != 3)
- usage
- exit
- end
- end
-
- def self.usage
- puts "Usage: #{$0} PATH ZIPFILENAME_PATTERN FILNAME_PATTERN"
- end
-
- def self.report_entry_found(fileName)
- puts fileName
- end
-
- end
-
- ZipFindConsoleRunner.run(ARGV)
-end
diff --git a/vendor/rubyzip-0.5.8/test/alltests.rb b/vendor/rubyzip-0.5.8/test/alltests.rb
deleted file mode 100644
index 691349af..00000000
--- a/vendor/rubyzip-0.5.8/test/alltests.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env ruby
-
-$VERBOSE = true
-
-require 'stdrubyexttest'
-require 'ioextrastest'
-require 'ziptest'
-require 'zipfilesystemtest'
-require 'ziprequiretest'
diff --git a/vendor/rubyzip-0.5.8/test/data/file1.txt b/vendor/rubyzip-0.5.8/test/data/file1.txt
deleted file mode 100644
index 23ea2f73..00000000
--- a/vendor/rubyzip-0.5.8/test/data/file1.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-
-AUTOMAKE_OPTIONS = gnu
-
-EXTRA_DIST = test.zip
-
-CXXFLAGS= -g
-
-noinst_LIBRARIES = libzipios.a
-
-bin_PROGRAMS = test_zip test_izipfilt test_izipstream
-# test_flist
-
-libzipios_a_SOURCES = backbuffer.h fcol.cpp fcol.h \
- fcol_common.h fcolexceptions.cpp fcolexceptions.h \
- fileentry.cpp fileentry.h flist.cpp \
- flist.h flistentry.cpp flistentry.h \
- flistscanner.h ifiltstreambuf.cpp ifiltstreambuf.h \
- inflatefilt.cpp inflatefilt.h izipfilt.cpp \
- izipfilt.h izipstream.cpp izipstream.h \
- zipfile.cpp zipfile.h ziphead.cpp \
- ziphead.h flistscanner.ll
-
-# test_flist_SOURCES = test_flist.cpp
-
-test_izipfilt_SOURCES = test_izipfilt.cpp
-
-test_izipstream_SOURCES = test_izipstream.cpp
-
-test_zip_SOURCES = test_zip.cpp
-
-# Notice that libzipios.a is not specified as -L. -lzipios
-# If it was, automake would not include it as a dependency.
-
-# test_flist_LDADD = libzipios.a
-
-test_izipfilt_LDADD = libzipios.a -lz
-
-test_zip_LDADD = libzipios.a -lz
-
-test_izipstream_LDADD = libzipios.a -lz
-
-
-
-flistscanner.cc : flistscanner.ll
- $(LEX) -+ -PFListScanner -o$@ $^
-
diff --git a/vendor/rubyzip-0.5.8/test/data/file1.txt.deflatedData b/vendor/rubyzip-0.5.8/test/data/file1.txt.deflatedData
deleted file mode 100644
index bfbb4f42c009154e9e3304855c31813275b709d6..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 482
zcmV<80UiE@RMBpmFcf{>{fa9!51TglfJv3cnzTZrO$4cwhiS+$rdV}s6dQHj*U#Vt
z3=5f`xX0%l?mad@^t@d^Mn6{hdb5q!PZ{3gi);W^yKNff%Q)Lw#4v5bKfDIG+wJa?
z=pnns-~~V`F15*%_4Ca
zj^EboH)XZqO6tya0#)-~Treih@%_}yQ1_j5gZaJAdUeEVT>IuDsQSN`rbJ4Y7;mF@
zf!i26zX>!yBbTKhhP8Aj^y*W$=fmwAo%K2sJ)!HNmwM3k8J!jDh3C2&Q7T4?A^j^}
z9r3Ik8+;@B3zEjD19@fmrW#RnN-n8r3f5ArlwiSXCJQF%
zdpJoZSw_p{^uI6;
YT71LBFMz*PQb9>fNlr&oR8>Ys3VC(y$N&HU
diff --git a/vendor/rubyzip-0.5.8/test/data/file2.txt b/vendor/rubyzip-0.5.8/test/data/file2.txt
deleted file mode 100644
index cc9ef6ad..00000000
--- a/vendor/rubyzip-0.5.8/test/data/file2.txt
+++ /dev/null
@@ -1,1504 +0,0 @@
-#!/usr/bin/env ruby
-
-$VERBOSE = true
-
-require 'rubyunit'
-require 'zip'
-
-include Zip
-
-Dir.chdir "test"
-
-class AbstractInputStreamTest < RUNIT::TestCase
- # AbstractInputStream subclass that provides a read method
-
- TEST_LINES = [ "Hello world#{$/}",
- "this is the second line#{$/}",
- "this is the last line"]
- TEST_STRING = TEST_LINES.join
- class TestAbstractInputStream
- include AbstractInputStream
- def initialize(aString)
- @contents = aString
- @readPointer = 0
- end
-
- def read(charsToRead)
- retVal=@contents[@readPointer, charsToRead]
- @readPointer+=charsToRead
- return retVal
- end
-
- def produceInput
- read(100)
- end
-
- def inputFinished?
- @contents[@readPointer] == nil
- end
- end
-
- def setup
- @io = TestAbstractInputStream.new(TEST_STRING)
- end
-
- def test_gets
- assert_equals(TEST_LINES[0], @io.gets)
- assert_equals(TEST_LINES[1], @io.gets)
- assert_equals(TEST_LINES[2], @io.gets)
- assert_equals(nil, @io.gets)
- end
-
- def test_getsMultiCharSeperator
- assert_equals("Hell", @io.gets("ll"))
- assert_equals("o world#{$/}this is the second l", @io.gets("d l"))
- end
-
- def test_each_line
- lineNumber=0
- @io.each_line {
- |line|
- assert_equals(TEST_LINES[lineNumber], line)
- lineNumber+=1
- }
- end
-
- def test_readlines
- assert_equals(TEST_LINES, @io.readlines)
- end
-
- def test_readline
- test_gets
- begin
- @io.readline
- fail "EOFError expected"
- rescue EOFError
- end
- end
-end
-
-class ZipEntryTest < RUNIT::TestCase
- TEST_ZIPFILE = "someZipFile.zip"
- TEST_COMMENT = "a comment"
- TEST_COMPRESSED_SIZE = 1234
- TEST_CRC = 325324
- TEST_EXTRA = "Some data here"
- TEST_COMPRESSIONMETHOD = ZipEntry::DEFLATED
- TEST_NAME = "entry name"
- TEST_SIZE = 8432
- TEST_ISDIRECTORY = false
-
- def test_constructorAndGetters
- entry = ZipEntry.new(TEST_ZIPFILE,
- TEST_NAME,
- TEST_COMMENT,
- TEST_EXTRA,
- TEST_COMPRESSED_SIZE,
- TEST_CRC,
- TEST_COMPRESSIONMETHOD,
- TEST_SIZE)
-
- assert_equals(TEST_COMMENT, entry.comment)
- assert_equals(TEST_COMPRESSED_SIZE, entry.compressedSize)
- assert_equals(TEST_CRC, entry.crc)
- assert_equals(TEST_EXTRA, entry.extra)
- assert_equals(TEST_COMPRESSIONMETHOD, entry.compressionMethod)
- assert_equals(TEST_NAME, entry.name)
- assert_equals(TEST_SIZE, entry.size)
- assert_equals(TEST_ISDIRECTORY, entry.isDirectory)
- end
-
- def test_equality
- entry1 = ZipEntry.new("file.zip", "name", "isNotCompared",
- "something extra", 123, 1234,
- ZipEntry::DEFLATED, 10000)
- entry2 = ZipEntry.new("file.zip", "name", "isNotComparedXXX",
- "something extra", 123, 1234,
- ZipEntry::DEFLATED, 10000)
- entry3 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
- "something extra", 123, 1234,
- ZipEntry::DEFLATED, 10000)
- entry4 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
- "something extraXX", 123, 1234,
- ZipEntry::DEFLATED, 10000)
- entry5 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
- "something extraXX", 12, 1234,
- ZipEntry::DEFLATED, 10000)
- entry6 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
- "something extraXX", 12, 123,
- ZipEntry::DEFLATED, 10000)
- entry7 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
- "something extraXX", 12, 123,
- ZipEntry::STORED, 10000)
- entry8 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
- "something extraXX", 12, 123,
- ZipEntry::STORED, 100000)
-
- assert_equals(entry1, entry1)
- assert_equals(entry1, entry2)
-
- assert(entry2 != entry3)
- assert(entry3 != entry4)
- assert(entry4 != entry5)
- assert(entry5 != entry6)
- assert(entry6 != entry7)
- assert(entry7 != entry8)
-
- assert(entry7 != "hello")
- assert(entry7 != 12)
- end
-end
-
-module IOizeString
- attr_reader :tell
-
- def read(count = nil)
- @tell ||= 0
- count = size unless count
- retVal = slice(@tell, count)
- @tell += count
- return retVal
- end
-
- def seek(index, offset)
- @tell ||= 0
- case offset
- when IO::SEEK_END
- newPos = size + index
- when IO::SEEK_SET
- newPos = index
- when IO::SEEK_CUR
- newPos = @tell + index
- else
- raise "Error in test method IOizeString::seek"
- end
- if (newPos < 0 || newPos >= size)
- raise Errno::EINVAL
- else
- @tell=newPos
- end
- end
-
- def reset
- @tell = 0
- end
-end
-
-class ZipLocalEntryTest < RUNIT::TestCase
- def test_readLocalEntryHeaderOfFirstTestZipEntry
- File.open(TestZipFile::TEST_ZIP3.zipName) {
- |file|
- entry = ZipEntry.readLocalEntry(file)
-
- assert_equal("", entry.comment)
- # Differs from windows and unix because of CR LF
- # assert_equal(480, entry.compressedSize)
- # assert_equal(0x2a27930f, entry.crc)
- # extra field is 21 bytes long
- # probably contains some unix attrutes or something
- # disabled: assert_equal(nil, entry.extra)
- assert_equal(ZipEntry::DEFLATED, entry.compressionMethod)
- assert_equal(TestZipFile::TEST_ZIP3.entryNames[0], entry.name)
- assert_equal(File.size(TestZipFile::TEST_ZIP3.entryNames[0]), entry.size)
- assert(! entry.isDirectory)
- }
- end
-
- def test_readLocalEntryFromNonZipFile
- File.open("ziptest.rb") {
- |file|
- assert_equals(nil, ZipEntry.readLocalEntry(file))
- }
- end
-
- def test_readLocalEntryFromTruncatedZipFile
- zipFragment=""
- File.open(TestZipFile::TEST_ZIP2.zipName) { |f| zipFragment = f.read(12) } # local header is at least 30 bytes
- zipFragment.extend(IOizeString).reset
- entry = ZipEntry.new
- entry.readLocalEntry(zipFragment)
- fail "ZipError expected"
- rescue ZipError
- end
-
- def test_writeEntry
- entry = ZipEntry.new("file.zip", "entryName", "my little comment",
- "thisIsSomeExtraInformation", 100, 987654,
- ZipEntry::DEFLATED, 400)
- writeToFile("localEntryHeader.bin", "centralEntryHeader.bin", entry)
- entryReadLocal, entryReadCentral = readFromFile("localEntryHeader.bin", "centralEntryHeader.bin")
- compareLocalEntryHeaders(entry, entryReadLocal)
- compareCDirEntryHeaders(entry, entryReadCentral)
- end
-
- private
- def compareLocalEntryHeaders(entry1, entry2)
- assert_equals(entry1.compressedSize , entry2.compressedSize)
- assert_equals(entry1.crc , entry2.crc)
- assert_equals(entry1.extra , entry2.extra)
- assert_equals(entry1.compressionMethod, entry2.compressionMethod)
- assert_equals(entry1.name , entry2.name)
- assert_equals(entry1.size , entry2.size)
- assert_equals(entry1.localHeaderOffset, entry2.localHeaderOffset)
- end
-
- def compareCDirEntryHeaders(entry1, entry2)
- compareLocalEntryHeaders(entry1, entry2)
- assert_equals(entry1.comment, entry2.comment)
- end
-
- def writeToFile(localFileName, centralFileName, entry)
- File.open(localFileName, "wb") { |f| entry.writeLocalEntry(f) }
- File.open(centralFileName, "wb") { |f| entry.writeCDirEntry(f) }
- end
-
- def readFromFile(localFileName, centralFileName)
- localEntry = nil
- cdirEntry = nil
- File.open(localFileName, "rb") { |f| localEntry = ZipEntry.readLocalEntry(f) }
- File.open(centralFileName, "rb") { |f| cdirEntry = ZipEntry.readCDirEntry(f) }
- return [localEntry, cdirEntry]
- end
-end
-
-
-module DecompressorTests
- # expects @refText and @decompressor
-
- def test_readEverything
- assert_equals(@refText, @decompressor.read)
- end
-
- def test_readInChunks
- chunkSize = 5
- while (decompressedChunk = @decompressor.read(chunkSize))
- assert_equals(@refText.slice!(0, chunkSize), decompressedChunk)
- end
- assert_equals(0, @refText.size)
- end
-end
-
-class InflaterTest < RUNIT::TestCase
- include DecompressorTests
-
- def setup
- @file = File.new("file1.txt.deflatedData", "rb")
- @refText=""
- File.open("file1.txt") { |f| @refText = f.read }
- @decompressor = Inflater.new(@file)
- end
-
- def teardown
- @file.close
- end
-end
-
-
-class PassThruDecompressorTest < RUNIT::TestCase
- include DecompressorTests
- TEST_FILE="file1.txt"
- def setup
- @file = File.new(TEST_FILE)
- @refText=""
- File.open(TEST_FILE) { |f| @refText = f.read }
- @decompressor = PassThruDecompressor.new(@file, File.size(TEST_FILE))
- end
-
- def teardown
- @file.close
- end
-end
-
-
-module AssertEntry
- def assertNextEntry(filename, zis)
- assertEntry(filename, zis, zis.getNextEntry.name)
- end
-
- def assertEntry(filename, zis, entryName)
- assert_equals(filename, entryName)
- assertEntryContentsForStream(filename, zis, entryName)
- end
-
- def assertEntryContentsForStream(filename, zis, entryName)
- File.open(filename, "rb") {
- |file|
- expected = file.read
- actual = zis.read
- if (expected != actual)
- if (expected.length > 400 || actual.length > 400)
- zipEntryFilename=entryName+".zipEntry"
- File.open(zipEntryFilename, "wb") { |file| file << actual }
- fail("File '#{filename}' is different from '#{zipEntryFilename}'")
- else
- assert_equals(expected, actual)
- end
- end
- }
- end
-
- def AssertEntry.assertContents(filename, aString)
- fileContents = ""
- File.open(filename, "rb") { |f| fileContents = f.read }
- if (fileContents != aString)
- if (expected.length > 400 || actual.length > 400)
- stringFile = filename + ".other"
- File.open(stringFile, "wb") { |f| f << aString }
- fail("File '#{filename}' is different from contents of string stored in '#{stringFile}'")
- else
- assert_equals(expected, actual)
- end
- end
- end
-
- def assertStreamContents(zis, testZipFile)
- assert(zis != nil)
- testZipFile.entryNames.each {
- |entryName|
- assertNextEntry(entryName, zis)
- }
- assert_equals(nil, zis.getNextEntry)
- end
-
- def assertTestZipContents(testZipFile)
- ZipInputStream.open(testZipFile.zipName) {
- |zis|
- assertStreamContents(zis, testZipFile)
- }
- end
-
- def assertEntryContents(zipFile, entryName, filename = entryName.to_s)
- zis = zipFile.getInputStream(entryName)
- assertEntryContentsForStream(filename, zis, entryName)
- ensure
- zis.close if zis
- end
-end
-
-
-
-class ZipInputStreamTest < RUNIT::TestCase
- include AssertEntry
-
- def test_new
- zis = ZipInputStream.new(TestZipFile::TEST_ZIP2.zipName)
- assertStreamContents(zis, TestZipFile::TEST_ZIP2)
- zis.close
- end
-
- def test_openWithBlock
- ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) {
- |zis|
- assertStreamContents(zis, TestZipFile::TEST_ZIP2)
- }
- end
-
- def test_openWithoutBlock
- zis = ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName)
- assertStreamContents(zis, TestZipFile::TEST_ZIP2)
- end
-
- def test_incompleteReads
- ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) {
- |zis|
- entry = zis.getNextEntry
- assert_equals(TestZipFile::TEST_ZIP2.entryNames[0], entry.name)
- assert zis.gets.length > 0
- entry = zis.getNextEntry
- assert_equals(TestZipFile::TEST_ZIP2.entryNames[1], entry.name)
- assert_equals(0, entry.size)
- assert_equals(nil, zis.gets)
- entry = zis.getNextEntry
- assert_equals(TestZipFile::TEST_ZIP2.entryNames[2], entry.name)
- assert zis.gets.length > 0
- entry = zis.getNextEntry
- assert_equals(TestZipFile::TEST_ZIP2.entryNames[3], entry.name)
- assert zis.gets.length > 0
- }
- end
-
-end
-
-class TestFiles
- RANDOM_ASCII_FILE1 = "randomAscii1.txt"
- RANDOM_ASCII_FILE2 = "randomAscii2.txt"
- RANDOM_ASCII_FILE3 = "randomAscii3.txt"
- RANDOM_BINARY_FILE1 = "randomBinary1.bin"
- RANDOM_BINARY_FILE2 = "randomBinary2.bin"
-
- EMPTY_TEST_DIR = "emptytestdir"
-
- ASCII_TEST_FILES = [ RANDOM_ASCII_FILE1, RANDOM_ASCII_FILE2, RANDOM_ASCII_FILE3 ]
- BINARY_TEST_FILES = [ RANDOM_BINARY_FILE1, RANDOM_BINARY_FILE2 ]
- TEST_DIRECTORIES = [ EMPTY_TEST_DIR ]
- TEST_FILES = [ ASCII_TEST_FILES, BINARY_TEST_FILES, EMPTY_TEST_DIR ].flatten!
-
- def TestFiles.createTestFiles(recreate)
- if (recreate ||
- ! (TEST_FILES.inject(true) { |accum, element| accum && File.exists?(element) }))
-
- ASCII_TEST_FILES.each_with_index {
- |filename, index|
- createRandomAscii(filename, 1E4 * (index+1))
- }
-
- BINARY_TEST_FILES.each_with_index {
- |filename, index|
- createRandomBinary(filename, 1E4 * (index+1))
- }
-
- ensureDir(EMPTY_TEST_DIR)
- end
- end
-
- private
- def TestFiles.createRandomAscii(filename, size)
- File.open(filename, "wb") {
- |file|
- while (file.tell < size)
- file << rand
- end
- }
- end
-
- def TestFiles.createRandomBinary(filename, size)
- File.open(filename, "wb") {
- |file|
- while (file.tell < size)
- file << rand.to_a.pack("V")
- end
- }
- end
-
- def TestFiles.ensureDir(name)
- if File.exists?(name)
- return if File.stat(name).directory?
- File.delete(name)
- end
- Dir.mkdir(name)
- end
-
-end
-
-# For representation and creation of
-# test data
-class TestZipFile
- attr_accessor :zipName, :entryNames, :comment
-
- def initialize(zipName, entryNames, comment = "")
- @zipName=zipName
- @entryNames=entryNames
- @comment = comment
- end
-
- def TestZipFile.createTestZips(recreate)
- files = Dir.entries(".")
- if (recreate ||
- ! (files.index(TEST_ZIP1.zipName) &&
- files.index(TEST_ZIP2.zipName) &&
- files.index(TEST_ZIP3.zipName) &&
- files.index(TEST_ZIP4.zipName) &&
- files.index("empty.txt") &&
- files.index("short.txt") &&
- files.index("longAscii.txt") &&
- files.index("longBinary.bin") ))
- raise "failed to create test zip '#{TEST_ZIP1.zipName}'" unless
- system("zip #{TEST_ZIP1.zipName} ziptest.rb")
- raise "failed to remove entry from '#{TEST_ZIP1.zipName}'" unless
- system("zip #{TEST_ZIP1.zipName} -d ziptest.rb")
-
- File.open("empty.txt", "w") {}
-
- File.open("short.txt", "w") { |file| file << "ABCDEF" }
- ziptestTxt=""
- File.open("ziptest.rb") { |file| ziptestTxt=file.read }
- File.open("longAscii.txt", "w") {
- |file|
- while (file.tell < 1E5)
- file << ziptestTxt
- end
- }
-
- testBinaryPattern=""
- File.open("empty.zip") { |file| testBinaryPattern=file.read }
- testBinaryPattern *= 4
-
- File.open("longBinary.bin", "wb") {
- |file|
- while (file.tell < 3E5)
- file << testBinaryPattern << rand
- end
- }
- raise "failed to create test zip '#{TEST_ZIP2.zipName}'" unless
- system("zip #{TEST_ZIP2.zipName} #{TEST_ZIP2.entryNames.join(' ')}")
-
- # without bash system interprets everything after echo as parameters to
- # echo including | zip -z ...
- raise "failed to add comment to test zip '#{TEST_ZIP2.zipName}'" unless
- system("bash -c \"echo #{TEST_ZIP2.comment} | zip -z #{TEST_ZIP2.zipName}\"")
-
- raise "failed to create test zip '#{TEST_ZIP3.zipName}'" unless
- system("zip #{TEST_ZIP3.zipName} #{TEST_ZIP3.entryNames.join(' ')}")
-
- raise "failed to create test zip '#{TEST_ZIP4.zipName}'" unless
- system("zip #{TEST_ZIP4.zipName} #{TEST_ZIP4.entryNames.join(' ')}")
- end
- rescue
- raise $!.to_s +
- "\n\nziptest.rb requires the Info-ZIP program 'zip' in the path\n" +
- "to create test data. If you don't have it you can download\n" +
- "the necessary test files at http://sf.net/projects/rubyzip."
- end
-
- TEST_ZIP1 = TestZipFile.new("empty.zip", [])
- TEST_ZIP2 = TestZipFile.new("4entry.zip", %w{ longAscii.txt empty.txt short.txt longBinary.bin},
- "my zip comment")
- TEST_ZIP3 = TestZipFile.new("test1.zip", %w{ file1.txt })
- TEST_ZIP4 = TestZipFile.new("zipWithDir.zip", [ "file1.txt",
- TestFiles::EMPTY_TEST_DIR])
-end
-
-
-class AbstractOutputStreamTest < RUNIT::TestCase
- class TestOutputStream
- include AbstractOutputStream
-
- attr_accessor :buffer
-
- def initialize
- @buffer = ""
- end
-
- def << (data)
- @buffer << data
- self
- end
- end
-
- def setup
- @outputStream = TestOutputStream.new
-
- @origCommaSep = $,
- @origOutputSep = $\
- end
-
- def teardown
- $, = @origCommaSep
- $\ = @origOutputSep
- end
-
- def test_write
- count = @outputStream.write("a little string")
- assert_equals("a little string", @outputStream.buffer)
- assert_equals("a little string".length, count)
-
- count = @outputStream.write(". a little more")
- assert_equals("a little string. a little more", @outputStream.buffer)
- assert_equals(". a little more".length, count)
- end
-
- def test_print
- $\ = nil # record separator set to nil
- @outputStream.print("hello")
- assert_equals("hello", @outputStream.buffer)
-
- @outputStream.print(" world.")
- assert_equals("hello world.", @outputStream.buffer)
-
- @outputStream.print(" You ok ", "out ", "there?")
- assert_equals("hello world. You ok out there?", @outputStream.buffer)
-
- $\ = "\n"
- @outputStream.print
- assert_equals("hello world. You ok out there?\n", @outputStream.buffer)
-
- @outputStream.print("I sure hope so!")
- assert_equals("hello world. You ok out there?\nI sure hope so!\n", @outputStream.buffer)
-
- $, = "X"
- @outputStream.buffer = ""
- @outputStream.print("monkey", "duck", "zebra")
- assert_equals("monkeyXduckXzebra\n", @outputStream.buffer)
-
- $\ = nil
- @outputStream.buffer = ""
- @outputStream.print(20)
- assert_equals("20", @outputStream.buffer)
- end
-
- def test_printf
- @outputStream.printf("%d %04x", 123, 123)
- assert_equals("123 007b", @outputStream.buffer)
- end
-
- def test_putc
- @outputStream.putc("A")
- assert_equals("A", @outputStream.buffer)
- @outputStream.putc(65)
- assert_equals("AA", @outputStream.buffer)
- end
-
- def test_puts
- @outputStream.puts
- assert_equals("\n", @outputStream.buffer)
-
- @outputStream.puts("hello", "world")
- assert_equals("\nhello\nworld\n", @outputStream.buffer)
-
- @outputStream.buffer = ""
- @outputStream.puts("hello\n", "world\n")
- assert_equals("hello\nworld\n", @outputStream.buffer)
-
- @outputStream.buffer = ""
- @outputStream.puts(["hello\n", "world\n"])
- assert_equals("hello\nworld\n", @outputStream.buffer)
-
- @outputStream.buffer = ""
- @outputStream.puts(["hello\n", "world\n"], "bingo")
- assert_equals("hello\nworld\nbingo\n", @outputStream.buffer)
-
- @outputStream.buffer = ""
- @outputStream.puts(16, 20, 50, "hello")
- assert_equals("16\n20\n50\nhello\n", @outputStream.buffer)
- end
-end
-
-
-module CrcTest
- def runCrcTest(compressorClass)
- str = "Here's a nice little text to compute the crc for! Ho hum, it is nice nice nice nice indeed."
- fakeOut = AbstractOutputStreamTest::TestOutputStream.new
-
- deflater = compressorClass.new(fakeOut)
- deflater << str
- assert_equals(0x919920fc, deflater.crc)
- end
-end
-
-
-
-class PassThruCompressorTest < RUNIT::TestCase
- include CrcTest
-
- def test_size
- File.open("dummy.txt", "wb") {
- |file|
- compressor = PassThruCompressor.new(file)
-
- assert_equals(0, compressor.size)
-
- t1 = "hello world"
- t2 = ""
- t3 = "bingo"
-
- compressor << t1
- assert_equals(compressor.size, t1.size)
-
- compressor << t2
- assert_equals(compressor.size, t1.size + t2.size)
-
- compressor << t3
- assert_equals(compressor.size, t1.size + t2.size + t3.size)
- }
- end
-
- def test_crc
- runCrcTest(PassThruCompressor)
- end
-end
-
-class DeflaterTest < RUNIT::TestCase
- include CrcTest
-
- def test_outputOperator
- txt = loadFile("ziptest.rb")
- deflate(txt, "deflatertest.bin")
- inflatedTxt = inflate("deflatertest.bin")
- assert_equals(txt, inflatedTxt)
- end
-
- private
- def loadFile(fileName)
- txt = nil
- File.open(fileName, "rb") { |f| txt = f.read }
- end
-
- def deflate(data, fileName)
- File.open(fileName, "wb") {
- |file|
- deflater = Deflater.new(file)
- deflater << data
- deflater.finish
- assert_equals(deflater.size, data.size)
- file << "trailing data for zlib with -MAX_WBITS"
- }
- end
-
- def inflate(fileName)
- txt = nil
- File.open(fileName, "rb") {
- |file|
- inflater = Inflater.new(file)
- txt = inflater.read
- }
- end
-
- def test_crc
- runCrcTest(Deflater)
- end
-end
-
-class ZipOutputStreamTest < RUNIT::TestCase
- include AssertEntry
-
- TEST_ZIP = TestZipFile::TEST_ZIP2.clone
- TEST_ZIP.zipName = "output.zip"
-
- def test_new
- zos = ZipOutputStream.new(TEST_ZIP.zipName)
- zos.comment = TEST_ZIP.comment
- writeTestZip(zos)
- zos.close
- assertTestZipContents(TEST_ZIP)
- end
-
- def test_open
- ZipOutputStream.open(TEST_ZIP.zipName) {
- |zos|
- zos.comment = TEST_ZIP.comment
- writeTestZip(zos)
- }
- assertTestZipContents(TEST_ZIP)
- end
-
- def test_writingToClosedStream
- assertIOErrorInClosedStream { |zos| zos << "hello world" }
- assertIOErrorInClosedStream { |zos| zos.puts "hello world" }
- assertIOErrorInClosedStream { |zos| zos.write "hello world" }
- end
-
- def test_cannotOpenFile
- name = TestFiles::EMPTY_TEST_DIR
- begin
- zos = ZipOutputStream.open(name)
- rescue Exception
- assert($!.kind_of?(Errno::EISDIR) || # Linux
- $!.kind_of?(Errno::EEXIST) || # Windows/cygwin
- $!.kind_of?(Errno::EACCES), # Windows
- "Expected Errno::EISDIR (or on win/cygwin: Errno::EEXIST), but was: #{$!.type}")
- end
- end
-
- def assertIOErrorInClosedStream
- assert_exception(IOError) {
- zos = ZipOutputStream.new("test_putOnClosedStream.zip")
- zos.close
- yield zos
- }
- end
-
- def writeTestZip(zos)
- TEST_ZIP.entryNames.each {
- |entryName|
- zos.putNextEntry(entryName)
- File.open(entryName, "rb") { |f| zos.write(f.read) }
- }
- end
-end
-
-
-
-module Enumerable
- def compareEnumerables(otherEnumerable)
- otherAsArray = otherEnumerable.to_a
- index=0
- each_with_index {
- |element, index|
- return false unless yield(element, otherAsArray[index])
- }
- return index+1 == otherAsArray.size
- end
-end
-
-
-class ZipCentralDirectoryEntryTest < RUNIT::TestCase
-
- def test_readFromStream
- File.open("testDirectory.bin", "rb") {
- |file|
- entry = ZipEntry.readCDirEntry(file)
-
- assert_equals("longAscii.txt", entry.name)
- assert_equals(ZipEntry::DEFLATED, entry.compressionMethod)
- assert_equals(106490, entry.size)
- assert_equals(3784, entry.compressedSize)
- assert_equals(0xfcd1799c, entry.crc)
- assert_equals("", entry.comment)
-
- entry = ZipEntry.readCDirEntry(file)
- assert_equals("empty.txt", entry.name)
- assert_equals(ZipEntry::STORED, entry.compressionMethod)
- assert_equals(0, entry.size)
- assert_equals(0, entry.compressedSize)
- assert_equals(0x0, entry.crc)
- assert_equals("", entry.comment)
-
- entry = ZipEntry.readCDirEntry(file)
- assert_equals("short.txt", entry.name)
- assert_equals(ZipEntry::STORED, entry.compressionMethod)
- assert_equals(6, entry.size)
- assert_equals(6, entry.compressedSize)
- assert_equals(0xbb76fe69, entry.crc)
- assert_equals("", entry.comment)
-
- entry = ZipEntry.readCDirEntry(file)
- assert_equals("longBinary.bin", entry.name)
- assert_equals(ZipEntry::DEFLATED, entry.compressionMethod)
- assert_equals(1000024, entry.size)
- assert_equals(70847, entry.compressedSize)
- assert_equals(0x10da7d59, entry.crc)
- assert_equals("", entry.comment)
-
- entry = ZipEntry.readCDirEntry(file)
- assert_equals(nil, entry)
-# Fields that are not check by this test:
-# version made by 2 bytes
-# version needed to extract 2 bytes
-# general purpose bit flag 2 bytes
-# last mod file time 2 bytes
-# last mod file date 2 bytes
-# compressed size 4 bytes
-# uncompressed size 4 bytes
-# disk number start 2 bytes
-# internal file attributes 2 bytes
-# external file attributes 4 bytes
-# relative offset of local header 4 bytes
-
-# file name (variable size)
-# extra field (variable size)
-# file comment (variable size)
-
- }
- end
-
- def test_ReadEntryFromTruncatedZipFile
- fragment=""
- File.open("testDirectory.bin") { |f| fragment = f.read(12) } # cdir entry header is at least 46 bytes
- fragment.extend(IOizeString)
- entry = ZipEntry.new
- entry.readCDirEntry(fragment)
- fail "ZipError expected"
- rescue ZipError
- end
-
-end
-
-class ZipCentralDirectoryTest < RUNIT::TestCase
-
- def test_readFromStream
- File.open(TestZipFile::TEST_ZIP2.zipName, "rb") {
- |zipFile|
- cdir = ZipCentralDirectory.readFromStream(zipFile)
-
- assert_equals(TestZipFile::TEST_ZIP2.entryNames.size, cdir.size)
- assert(cdir.compareEnumerables(TestZipFile::TEST_ZIP2.entryNames) {
- |cdirEntry, testEntryName|
- cdirEntry.name == testEntryName
- })
- assert_equals(TestZipFile::TEST_ZIP2.comment, cdir.comment)
- }
- end
-
- def test_readFromInvalidStream
- File.open("ziptest.rb", "rb") {
- |zipFile|
- cdir = ZipCentralDirectory.new
- cdir.readFromStream(zipFile)
- }
- fail "ZipError expected!"
- rescue ZipError
- end
-
- def test_ReadFromTruncatedZipFile
- fragment=""
- File.open("testDirectory.bin") { |f| fragment = f.read }
- fragment.slice!(12) # removed part of first cdir entry. eocd structure still complete
- fragment.extend(IOizeString)
- entry = ZipCentralDirectory.new
- entry.readFromStream(fragment)
- fail "ZipError expected"
- rescue ZipError
- end
-
- def test_writeToStream
- entries = [ ZipEntry.new("file.zip", "flimse", "myComment", "somethingExtra"),
- ZipEntry.new("file.zip", "secondEntryName"),
- ZipEntry.new("file.zip", "lastEntry.txt", "Has a comment too") ]
- cdir = ZipCentralDirectory.new(entries, "my zip comment")
- File.open("cdirtest.bin", "wb") { |f| cdir.writeToStream(f) }
- cdirReadback = ZipCentralDirectory.new
- File.open("cdirtest.bin", "rb") { |f| cdirReadback.readFromStream(f) }
-
- assert_equals(cdir.entries, cdirReadback.entries)
- end
-
- def test_equality
- cdir1 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
- "somethingExtra"),
- ZipEntry.new("file.zip", "secondEntryName"),
- ZipEntry.new("file.zip", "lastEntry.txt") ],
- "my zip comment")
- cdir2 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
- "somethingExtra"),
- ZipEntry.new("file.zip", "secondEntryName"),
- ZipEntry.new("file.zip", "lastEntry.txt") ],
- "my zip comment")
- cdir3 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
- "somethingExtra"),
- ZipEntry.new("file.zip", "secondEntryName"),
- ZipEntry.new("file.zip", "lastEntry.txt") ],
- "comment?")
- cdir4 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
- "somethingExtra"),
- ZipEntry.new("file.zip", "lastEntry.txt") ],
- "comment?")
- assert_equals(cdir1, cdir1)
- assert_equals(cdir1, cdir2)
-
- assert(cdir1 != cdir3)
- assert(cdir2 != cdir3)
- assert(cdir2 != cdir3)
- assert(cdir3 != cdir4)
-
- assert(cdir3 != "hello")
- end
-end
-
-
-class BasicZipFileTest < RUNIT::TestCase
- include AssertEntry
-
- def setup
- @zipFile = ZipFile.new(TestZipFile::TEST_ZIP2.zipName)
- @testEntryNameIndex=0
- end
-
- def nextTestEntryName
- retVal=TestZipFile::TEST_ZIP2.entryNames[@testEntryNameIndex]
- @testEntryNameIndex+=1
- return retVal
- end
-
- def test_entries
- assert_equals(TestZipFile::TEST_ZIP2.entryNames, @zipFile.entries.map {|e| e.name} )
- end
-
- def test_each
- @zipFile.each {
- |entry|
- assert_equals(nextTestEntryName, entry.name)
- }
- assert_equals(4, @testEntryNameIndex)
- end
-
- def test_foreach
- ZipFile.foreach(TestZipFile::TEST_ZIP2.zipName) {
- |entry|
- assert_equals(nextTestEntryName, entry.name)
- }
- assert_equals(4, @testEntryNameIndex)
- end
-
- def test_getInputStream
- @zipFile.each {
- |entry|
- assertEntry(nextTestEntryName, @zipFile.getInputStream(entry),
- entry.name)
- }
- assert_equals(4, @testEntryNameIndex)
- end
-
- def test_getInputStreamBlock
- fileAndEntryName = @zipFile.entries.first.name
- @zipFile.getInputStream(fileAndEntryName) {
- |zis|
- assertEntryContentsForStream(fileAndEntryName,
- zis,
- fileAndEntryName)
- }
- end
-end
-
-class CommonZipFileFixture < RUNIT::TestCase
- include AssertEntry
-
- EMPTY_FILENAME = "emptyZipFile.zip"
-
- TEST_ZIP = TestZipFile::TEST_ZIP2.clone
- TEST_ZIP.zipName = "4entry_copy.zip"
-
- def setup
- File.delete(EMPTY_FILENAME) if File.exists?(EMPTY_FILENAME)
- File.copy(TestZipFile::TEST_ZIP2.zipName, TEST_ZIP.zipName)
- end
-end
-
-class ZipFileTest < CommonZipFileFixture
-
- def test_createFromScratch
- comment = "a short comment"
-
- zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE)
- zf.comment = comment
- zf.close
-
- zfRead = ZipFile.new(EMPTY_FILENAME)
- assert_equals(comment, zfRead.comment)
- assert_equals(0, zfRead.entries.length)
- end
-
- def test_add
- srcFile = "ziptest.rb"
- entryName = "newEntryName.rb"
- assert(File.exists? srcFile)
- zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE)
- zf.add(entryName, srcFile)
- zf.close
-
- zfRead = ZipFile.new(EMPTY_FILENAME)
- assert_equals("", zfRead.comment)
- assert_equals(1, zfRead.entries.length)
- assert_equals(entryName, zfRead.entries.first.name)
- AssertEntry.assertContents(srcFile,
- zfRead.getInputStream(entryName) { |zis| zis.read })
- end
-
- def test_addExistingEntryName
- assert_exception(ZipEntryExistsError) {
- ZipFile.open(TEST_ZIP.zipName) {
- |zf|
- zf.add(zf.entries.first.name, "ziptest.rb")
- }
- }
- end
-
- def test_addExistingEntryNameReplace
- gotCalled = false
- replacedEntry = nil
- ZipFile.open(TEST_ZIP.zipName) {
- |zf|
- replacedEntry = zf.entries.first.name
- zf.add(replacedEntry, "ziptest.rb") { gotCalled = true; true }
- }
- assert(gotCalled)
- ZipFile.open(TEST_ZIP.zipName) {
- |zf|
- assertContains(zf, replacedEntry, "ziptest.rb")
- }
- end
-
- def test_addDirectory
- ZipFile.open(TEST_ZIP.zipName) {
- |zf|
- zf.add(TestFiles::EMPTY_TEST_DIR, TestFiles::EMPTY_TEST_DIR)
- }
- ZipFile.open(TEST_ZIP.zipName) {
- |zf|
- dirEntry = zf.entries.detect { |e| e.name == TestFiles::EMPTY_TEST_DIR+"/" }
- assert(dirEntry.isDirectory)
- }
- end
-
- def test_remove
- entryToRemove, *remainingEntries = TEST_ZIP.entryNames
-
- File.copy(TestZipFile::TEST_ZIP2.zipName, TEST_ZIP.zipName)
-
- zf = ZipFile.new(TEST_ZIP.zipName)
- assert(zf.entries.map { |e| e.name }.include?(entryToRemove))
- zf.remove(entryToRemove)
- assert(! zf.entries.map { |e| e.name }.include?(entryToRemove))
- assert_equals(zf.entries.map {|x| x.name }.sort, remainingEntries.sort)
- zf.close
-
- zfRead = ZipFile.new(TEST_ZIP.zipName)
- assert(! zfRead.entries.map { |e| e.name }.include?(entryToRemove))
- assert_equals(zfRead.entries.map {|x| x.name }.sort, remainingEntries.sort)
- zfRead.close
- end
-
-
- def test_rename
- entryToRename, *remainingEntries = TEST_ZIP.entryNames
-
- zf = ZipFile.new(TEST_ZIP.zipName)
- assert(zf.entries.map { |e| e.name }.include? entryToRename)
-
- newName = "changed name"
- assert(! zf.entries.map { |e| e.name }.include?(newName))
-
- zf.rename(entryToRename, newName)
- assert(zf.entries.map { |e| e.name }.include? newName)
-
- zf.close
-
- zfRead = ZipFile.new(TEST_ZIP.zipName)
- assert(zfRead.entries.map { |e| e.name }.include? newName)
- zfRead.close
- end
-
- def test_renameToExistingEntry
- oldEntries = nil
- ZipFile.open(TEST_ZIP.zipName) { |zf| oldEntries = zf.entries }
-
- assert_exception(ZipEntryExistsError) {
- ZipFile.open(TEST_ZIP.zipName) {
- |zf|
- zf.rename(zf.entries[0], zf.entries[1].name)
- }
- }
-
- ZipFile.open(TEST_ZIP.zipName) {
- |zf|
- assert_equals(oldEntries.map{ |e| e.name }, zf.entries.map{ |e| e.name })
- }
- end
-
- def test_renameToExistingEntryOverwrite
- oldEntries = nil
- ZipFile.open(TEST_ZIP.zipName) { |zf| oldEntries = zf.entries }
-
- gotCalled = false
- ZipFile.open(TEST_ZIP.zipName) {
- |zf|
- zf.rename(zf.entries[0], zf.entries[1].name) { gotCalled = true; true }
- }
-
- assert(gotCalled)
- oldEntries.delete_at(0)
- ZipFile.open(TEST_ZIP.zipName) {
- |zf|
- assert_equals(oldEntries.map{ |e| e.name },
- zf.entries.map{ |e| e.name })
- }
- end
-
- def test_renameNonEntry
- nonEntry = "bogusEntry"
- targetEntry = "targetEntryName"
- zf = ZipFile.new(TEST_ZIP.zipName)
- assert(! zf.entries.include?(nonEntry))
- assert_exception(ZipNoSuchEntryError) {
- zf.rename(nonEntry, targetEntry)
- }
- zf.commit
- assert(! zf.entries.include?(targetEntry))
- ensure
- zf.close
- end
-
- def test_renameEntryToExistingEntry
- entry1, entry2, *remaining = TEST_ZIP.entryNames
- zf = ZipFile.new(TEST_ZIP.zipName)
- assert_exception(ZipEntryExistsError) {
- zf.rename(entry1, entry2)
- }
- ensure
- zf.close
- end
-
- def test_replace
- unchangedEntries = TEST_ZIP.entryNames.dup
- entryToReplace = unchangedEntries.delete_at(2)
- newEntrySrcFilename = "ziptest.rb"
-
- zf = ZipFile.new(TEST_ZIP.zipName)
- zf.replace(entryToReplace, newEntrySrcFilename)
-
- zf.close
-
- zfRead = ZipFile.new(TEST_ZIP.zipName)
- AssertEntry::assertContents(newEntrySrcFilename,
- zfRead.getInputStream(entryToReplace) { |is| is.read })
- zfRead.close
- end
-
- def test_replaceNonEntry
- entryToReplace = "nonExistingEntryname"
- ZipFile.open(TEST_ZIP.zipName) {
- |zf|
- assert_exception(ZipNoSuchEntryError) {
- zf.replace(entryToReplace, "ziptest.rb")
- }
- }
- end
-
- def test_commit
- newName = "renamedFirst"
- zf = ZipFile.new(TEST_ZIP.zipName)
- oldName = zf.entries.first
- zf.rename(oldName, newName)
- zf.commit
-
- zfRead = ZipFile.new(TEST_ZIP.zipName)
- assert(zfRead.entries.detect { |e| e.name == newName } != nil)
- assert(zfRead.entries.detect { |e| e.name == oldName } == nil)
- zfRead.close
-
- zf.close
- end
-
- # This test tests that after commit, you
- # can delete the file you used to add the entry to the zip file
- # with
- def test_commitUseZipEntry
- File.copy(TestFiles::RANDOM_ASCII_FILE1, "okToDelete.txt")
- zf = ZipFile.open(TEST_ZIP.zipName)
- zf.add("okToDelete.txt", "okToDelete.txt")
- assertContains(zf, "okToDelete.txt")
- zf.commit
- File.move("okToDelete.txt", "okToDeleteMoved.txt")
- assertContains(zf, "okToDelete.txt", "okToDeleteMoved.txt")
- end
-
-# def test_close
-# zf = ZipFile.new(TEST_ZIP.zipName)
-# zf.close
-# assert_exception(IOError) {
-# zf.extract(TEST_ZIP.entryNames.first, "hullubullu")
-# }
-# end
-
- def test_compound1
- renamedName = "renamedName"
- originalEntries = []
- begin
- zf = ZipFile.new(TEST_ZIP.zipName)
- originalEntries = zf.entries.dup
-
- assertNotContains(zf, TestFiles::RANDOM_ASCII_FILE1)
- zf.add(TestFiles::RANDOM_ASCII_FILE1,
- TestFiles::RANDOM_ASCII_FILE1)
- assertContains(zf, TestFiles::RANDOM_ASCII_FILE1)
-
- zf.rename(zf.entries[0], renamedName)
- assertContains(zf, renamedName)
-
- TestFiles::BINARY_TEST_FILES.each {
- |filename|
- zf.add(filename, filename)
- assertContains(zf, filename)
- }
-
- assertContains(zf, originalEntries.last.to_s)
- zf.remove(originalEntries.last.to_s)
- assertNotContains(zf, originalEntries.last.to_s)
-
- ensure
- zf.close
- end
- begin
- zfRead = ZipFile.new(TEST_ZIP.zipName)
- assertContains(zfRead, TestFiles::RANDOM_ASCII_FILE1)
- assertContains(zfRead, renamedName)
- TestFiles::BINARY_TEST_FILES.each {
- |filename|
- assertContains(zfRead, filename)
- }
- assertNotContains(zfRead, originalEntries.last.to_s)
- ensure
- zfRead.close
- end
- end
-
- def test_compound2
- begin
- zf = ZipFile.new(TEST_ZIP.zipName)
- originalEntries = zf.entries.dup
-
- originalEntries.each {
- |entry|
- zf.remove(entry)
- assertNotContains(zf, entry)
- }
- assert(zf.entries.empty?)
-
- TestFiles::ASCII_TEST_FILES.each {
- |filename|
- zf.add(filename, filename)
- assertContains(zf, filename)
- }
- assert_equals(zf.entries.map { |e| e.name }, TestFiles::ASCII_TEST_FILES)
-
- zf.rename(TestFiles::ASCII_TEST_FILES[0], "newName")
- assertNotContains(zf, TestFiles::ASCII_TEST_FILES[0])
- assertContains(zf, "newName")
- ensure
- zf.close
- end
- begin
- zfRead = ZipFile.new(TEST_ZIP.zipName)
- asciiTestFiles = TestFiles::ASCII_TEST_FILES.dup
- asciiTestFiles.shift
- asciiTestFiles.each {
- |filename|
- assertContains(zf, filename)
- }
-
- assertContains(zf, "newName")
- ensure
- zfRead.close
- end
- end
-
- private
- def assertContains(zf, entryName, filename = entryName)
- assert(zf.entries.detect { |e| e.name == entryName} != nil, "entry #{entryName} not in #{zf.entries.join(', ')} in zip file #{zf}")
- assertEntryContents(zf, entryName, filename) if File.exists?(filename)
- end
-
- def assertNotContains(zf, entryName)
- assert(zf.entries.detect { |e| e.name == entryName} == nil, "entry #{entryName} in #{zf.entries.join(', ')} in zip file #{zf}")
- end
-end
-
-class ZipFileExtractTest < CommonZipFileFixture
- EXTRACTED_FILENAME = "extEntry"
- ENTRY_TO_EXTRACT, *REMAINING_ENTRIES = TEST_ZIP.entryNames.reverse
-
- def setup
- super
- File.delete(EXTRACTED_FILENAME) if File.exists?(EXTRACTED_FILENAME)
- end
-
- def test_extract
- ZipFile.open(TEST_ZIP.zipName) {
- |zf|
- zf.extract(ENTRY_TO_EXTRACT, EXTRACTED_FILENAME)
-
- assert(File.exists? EXTRACTED_FILENAME)
- AssertEntry::assertContents(EXTRACTED_FILENAME,
- zf.getInputStream(ENTRY_TO_EXTRACT) { |is| is.read })
- }
- end
-
- def test_extractExists
- writtenText = "written text"
- File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) }
-
- assert_exception(ZipDestinationFileExistsError) {
- ZipFile.open(TEST_ZIP.zipName) {
- |zf|
- zf.extract(zf.entries.first, EXTRACTED_FILENAME)
- }
- }
- File.open(EXTRACTED_FILENAME, "r") {
- |f|
- assert_equals(writtenText, f.read)
- }
- end
-
- def test_extractExistsOverwrite
- writtenText = "written text"
- File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) }
-
- gotCalled = false
- ZipFile.open(TEST_ZIP.zipName) {
- |zf|
- zf.extract(zf.entries.first, EXTRACTED_FILENAME) { gotCalled = true; true }
- }
-
- assert(gotCalled)
- File.open(EXTRACTED_FILENAME, "r") {
- |f|
- assert(writtenText != f.read)
- }
- end
-
- def test_extractNonEntry
- zf = ZipFile.new(TEST_ZIP.zipName)
- assert_exception(ZipNoSuchEntryError) { zf.extract("nonExistingEntry", "nonExistingEntry") }
- ensure
- zf.close if zf
- end
-
- def test_extractNonEntry2
- outFile = "outfile"
- assert_exception(ZipNoSuchEntryError) {
- zf = ZipFile.new(TEST_ZIP.zipName)
- nonEntry = "hotdog-diddelidoo"
- assert(! zf.entries.include?(nonEntry))
- zf.extract(nonEntry, outFile)
- zf.close
- }
- assert(! File.exists?(outFile))
- end
-
-end
-
-class ZipFileExtractDirectoryTest < CommonZipFileFixture
- TEST_OUT_NAME = "emptyOutDir"
-
- def openZip(&aProc)
- assert(aProc != nil)
- ZipFile.open(TestZipFile::TEST_ZIP4.zipName, &aProc)
- end
-
- def extractTestDir(&aProc)
- openZip {
- |zf|
- zf.extract(TestFiles::EMPTY_TEST_DIR, TEST_OUT_NAME, &aProc)
- }
- end
-
- def setup
- super
-
- Dir.rmdir(TEST_OUT_NAME) if File.directory? TEST_OUT_NAME
- File.delete(TEST_OUT_NAME) if File.exists? TEST_OUT_NAME
- end
-
- def test_extractDirectory
- extractTestDir
- assert(File.directory? TEST_OUT_NAME)
- end
-
- def test_extractDirectoryExistsAsDir
- Dir.mkdir TEST_OUT_NAME
- extractTestDir
- assert(File.directory? TEST_OUT_NAME)
- end
-
- def test_extractDirectoryExistsAsFile
- File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" }
- assert_exception(ZipDestinationFileExistsError) { extractTestDir }
- end
-
- def test_extractDirectoryExistsAsFileOverwrite
- File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" }
- gotCalled = false
- extractTestDir {
- |entry, destPath|
- gotCalled = true
- assert_equals(TEST_OUT_NAME, destPath)
- assert(entry.isDirectory)
- true
- }
- assert(gotCalled)
- assert(File.directory? TEST_OUT_NAME)
- end
-end
-
-
-TestFiles::createTestFiles(ARGV.index("recreate") != nil ||
- ARGV.index("recreateonly") != nil)
-TestZipFile::createTestZips(ARGV.index("recreate") != nil ||
- ARGV.index("recreateonly") != nil)
-exit if ARGV.index("recreateonly") != nil
-
-#require 'runit/cui/testrunner'
-#RUNIT::CUI::TestRunner.run(ZipFileTest.suite)
-
-# Copyright (C) 2002 Thomas Sondergaard
-# rubyzip is free software; you can redistribute it and/or
-# modify it under the terms of the ruby license.
diff --git a/vendor/rubyzip-0.5.8/test/data/notzippedruby.rb b/vendor/rubyzip-0.5.8/test/data/notzippedruby.rb
deleted file mode 100644
index 036d25e9..00000000
--- a/vendor/rubyzip-0.5.8/test/data/notzippedruby.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env ruby
-
-class NotZippedRuby
- def returnTrue
- true
- end
-end
diff --git a/vendor/rubyzip-0.5.8/test/data/rubycode.zip b/vendor/rubyzip-0.5.8/test/data/rubycode.zip
deleted file mode 100644
index 8a68560e638088df79cd3bf68973013e5421a138..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 617
zcmWIWW@Zs#U|`^2*ef_ihjAyDyLz4#a#6q6}4;1qG=oMWsoVhI&Owp&^_M%*Qqz
zusOT^fK6xx3qz{5pk{E`6@6X3Oa7XQ6aq^YrF$udom<7Oc6lM6}=RDLT(4ef%v0bc!4h^8y1W
zF(|b-zqBYhRj;I?1ROS-fZ>81HlI)HpFDBKJKSTf$2lEFL!-|k4N6D3GG|(@>;ig~
zkx85xSJ3kU?ONSo@jDa*vNRhlwoTaWDdGpXl_l7YYQ5=Tcy
zrKJm6mDneFo%MeBlu4K&z?+dtoEeupd4aBFU|
zA4oGE-6BAHIKZ|xRwx*G19_o9EQG2%Ei)(8(9jU>1duaeP7pnEkh8&nhxJ1B@*nf6
zHmC3$*O)cQq4xsI(%Y*)R4Bgs(PD5T$>)hP`&4@^Uu)sOHmP%+3H(JZ*Tj$A;8upFq4-#D)-_!rOo
zz!GmJQzzjm|Ki#?1CQIcEI2yj#PYsPrf+proq4ajTwpGhS;Rkm%D0A)zZ8EJcxCc?6yCYU#-$Z+V)|>29qyQgrU)ZKDMG0hH6=mA&`2McB8;FZB0rGW
z^aM>2Fx?OquacTrK4QqJHwn1X`eeKbzSH2tf
ze~@$y7Fr=VYr&WAVTm&&(+zp%a4xxL^+-`ycmB2e%C1^V4FwljSkE~#@%Fi*%OZ!K
zJ;>Ryr7T6HD!}#Rvky$Dk$dY_Uj ZipEntry.new("zf.zip", "a")))
- assert_equal(1, (ZipEntry.new("zf.zip", "b") <=> ZipEntry.new("zf.zip", "a")))
- assert_equal(-1, (ZipEntry.new("zf.zip", "a") <=> ZipEntry.new("zf.zip", "b")))
-
- entries = [
- ZipEntry.new("zf.zip", "5"),
- ZipEntry.new("zf.zip", "1"),
- ZipEntry.new("zf.zip", "3"),
- ZipEntry.new("zf.zip", "4"),
- ZipEntry.new("zf.zip", "0"),
- ZipEntry.new("zf.zip", "2")
- ]
-
- entries.sort!
- assert_equal("0", entries[0].to_s)
- assert_equal("1", entries[1].to_s)
- assert_equal("2", entries[2].to_s)
- assert_equal("3", entries[3].to_s)
- assert_equal("4", entries[4].to_s)
- assert_equal("5", entries[5].to_s)
- end
-
- def test_parentAsString
- entry1 = ZipEntry.new("zf.zip", "aa")
- entry2 = ZipEntry.new("zf.zip", "aa/")
- entry3 = ZipEntry.new("zf.zip", "aa/bb")
- entry4 = ZipEntry.new("zf.zip", "aa/bb/")
- entry5 = ZipEntry.new("zf.zip", "aa/bb/cc")
- entry6 = ZipEntry.new("zf.zip", "aa/bb/cc/")
-
- assert_equal(nil, entry1.parent_as_string)
- assert_equal(nil, entry2.parent_as_string)
- assert_equal("aa/", entry3.parent_as_string)
- assert_equal("aa/", entry4.parent_as_string)
- assert_equal("aa/bb/", entry5.parent_as_string)
- assert_equal("aa/bb/", entry6.parent_as_string)
- end
-
- def test_entry_name_cannot_start_with_slash
- assert_raise(ZipEntryNameError) { ZipEntry.new("zf.zip", "/hej/der") }
- end
-end
-
-module IOizeString
- attr_reader :tell
-
- def read(count = nil)
- @tell ||= 0
- count = size unless count
- retVal = slice(@tell, count)
- @tell += count
- return retVal
- end
-
- def seek(index, offset)
- @tell ||= 0
- case offset
- when IO::SEEK_END
- newPos = size + index
- when IO::SEEK_SET
- newPos = index
- when IO::SEEK_CUR
- newPos = @tell + index
- else
- raise "Error in test method IOizeString::seek"
- end
- if (newPos < 0 || newPos >= size)
- raise Errno::EINVAL
- else
- @tell=newPos
- end
- end
-
- def reset
- @tell = 0
- end
-end
-
-class ZipLocalEntryTest < Test::Unit::TestCase
- def test_read_local_entryHeaderOfFirstTestZipEntry
- File.open(TestZipFile::TEST_ZIP3.zip_name, "rb") {
- |file|
- entry = ZipEntry.read_local_entry(file)
-
- assert_equal("", entry.comment)
- # Differs from windows and unix because of CR LF
- # assert_equal(480, entry.compressed_size)
- # assert_equal(0x2a27930f, entry.crc)
- # extra field is 21 bytes long
- # probably contains some unix attrutes or something
- # disabled: assert_equal(nil, entry.extra)
- assert_equal(ZipEntry::DEFLATED, entry.compression_method)
- assert_equal(TestZipFile::TEST_ZIP3.entry_names[0], entry.name)
- assert_equal(File.size(TestZipFile::TEST_ZIP3.entry_names[0]), entry.size)
- assert(! entry.is_directory)
- }
- end
-
- def test_readDateTime
- File.open("data/rubycode.zip", "rb") {
- |file|
- entry = ZipEntry.read_local_entry(file)
- assert_equal("zippedruby1.rb", entry.name)
- assert_equal(Time.at(1019261638), entry.time)
- }
- end
-
- def test_read_local_entryFromNonZipFile
- File.open("data/file2.txt") {
- |file|
- assert_equal(nil, ZipEntry.read_local_entry(file))
- }
- end
-
- def test_read_local_entryFromTruncatedZipFile
- zipFragment=""
- File.open(TestZipFile::TEST_ZIP2.zip_name) { |f| zipFragment = f.read(12) } # local header is at least 30 bytes
- zipFragment.extend(IOizeString).reset
- entry = ZipEntry.new
- entry.read_local_entry(zipFragment)
- fail "ZipError expected"
- rescue ZipError
- end
-
- def test_writeEntry
- entry = ZipEntry.new("file.zip", "entryName", "my little comment",
- "thisIsSomeExtraInformation", 100, 987654,
- ZipEntry::DEFLATED, 400)
- write_to_file("localEntryHeader.bin", "centralEntryHeader.bin", entry)
- entryReadLocal, entryReadCentral = read_from_file("localEntryHeader.bin", "centralEntryHeader.bin")
- compare_local_entry_headers(entry, entryReadLocal)
- compare_c_dir_entry_headers(entry, entryReadCentral)
- end
-
- private
- def compare_local_entry_headers(entry1, entry2)
- assert_equal(entry1.compressed_size , entry2.compressed_size)
- assert_equal(entry1.crc , entry2.crc)
- assert_equal(entry1.extra , entry2.extra)
- assert_equal(entry1.compression_method, entry2.compression_method)
- assert_equal(entry1.name , entry2.name)
- assert_equal(entry1.size , entry2.size)
- assert_equal(entry1.localHeaderOffset, entry2.localHeaderOffset)
- end
-
- def compare_c_dir_entry_headers(entry1, entry2)
- compare_local_entry_headers(entry1, entry2)
- assert_equal(entry1.comment, entry2.comment)
- end
-
- def write_to_file(localFileName, centralFileName, entry)
- File.open(localFileName, "wb") { |f| entry.write_local_entry(f) }
- File.open(centralFileName, "wb") { |f| entry.write_c_dir_entry(f) }
- end
-
- def read_from_file(localFileName, centralFileName)
- localEntry = nil
- cdirEntry = nil
- File.open(localFileName, "rb") { |f| localEntry = ZipEntry.read_local_entry(f) }
- File.open(centralFileName, "rb") { |f| cdirEntry = ZipEntry.read_c_dir_entry(f) }
- return [localEntry, cdirEntry]
- end
-end
-
-
-module DecompressorTests
- # expects @refText, @refLines and @decompressor
-
- TEST_FILE="data/file1.txt"
-
- def setup
- @refText=""
- File.open(TEST_FILE) { |f| @refText = f.read }
- @refLines = @refText.split($/)
- end
-
- def test_readEverything
- assert_equal(@refText, @decompressor.read)
- end
-
- def test_readInChunks
- chunkSize = 5
- while (decompressedChunk = @decompressor.read(chunkSize))
- assert_equal(@refText.slice!(0, chunkSize), decompressedChunk)
- end
- assert_equal(0, @refText.size)
- end
-
- def test_mixingReadsAndProduceInput
- # Just some preconditions to make sure we have enough data for this test
- assert(@refText.length > 1000)
- assert(@refLines.length > 40)
-
-
- assert_equal(@refText[0...100], @decompressor.read(100))
-
- assert(! @decompressor.input_finished?)
- buf = @decompressor.produce_input
- assert_equal(@refText[100...(100+buf.length)], buf)
- end
-end
-
-class InflaterTest < Test::Unit::TestCase
- include DecompressorTests
-
- def setup
- super
- @file = File.new("data/file1.txt.deflatedData", "rb")
- @decompressor = Inflater.new(@file)
- end
-
- def teardown
- @file.close
- end
-end
-
-
-class PassThruDecompressorTest < Test::Unit::TestCase
- include DecompressorTests
- def setup
- super
- @file = File.new(TEST_FILE)
- @decompressor = PassThruDecompressor.new(@file, File.size(TEST_FILE))
- end
-
- def teardown
- @file.close
- end
-end
-
-
-module AssertEntry
- def assert_next_entry(filename, zis)
- assert_entry(filename, zis, zis.get_next_entry.name)
- end
-
- def assert_entry(filename, zis, entryName)
- assert_equal(filename, entryName)
- assert_entryContentsForStream(filename, zis, entryName)
- end
-
- def assert_entryContentsForStream(filename, zis, entryName)
- File.open(filename, "rb") {
- |file|
- expected = file.read
- actual = zis.read
- if (expected != actual)
- if ((expected && actual) && (expected.length > 400 || actual.length > 400))
- zipEntryFilename=entryName+".zipEntry"
- File.open(zipEntryFilename, "wb") { |file| file << actual }
- fail("File '#{filename}' is different from '#{zipEntryFilename}'")
- else
- assert_equal(expected, actual)
- end
- end
- }
- end
-
- def AssertEntry.assert_contents(filename, aString)
- fileContents = ""
- File.open(filename, "rb") { |f| fileContents = f.read }
- if (fileContents != aString)
- if (fileContents.length > 400 || aString.length > 400)
- stringFile = filename + ".other"
- File.open(stringFile, "wb") { |f| f << aString }
- fail("File '#{filename}' is different from contents of string stored in '#{stringFile}'")
- else
- assert_equal(fileContents, aString)
- end
- end
- end
-
- def assert_stream_contents(zis, testZipFile)
- assert(zis != nil)
- testZipFile.entry_names.each {
- |entryName|
- assert_next_entry(entryName, zis)
- }
- assert_equal(nil, zis.get_next_entry)
- end
-
- def assert_test_zip_contents(testZipFile)
- ZipInputStream.open(testZipFile.zip_name) {
- |zis|
- assert_stream_contents(zis, testZipFile)
- }
- end
-
- def assert_entryContents(zipFile, entryName, filename = entryName.to_s)
- zis = zipFile.get_input_stream(entryName)
- assert_entryContentsForStream(filename, zis, entryName)
- ensure
- zis.close if zis
- end
-end
-
-
-
-class ZipInputStreamTest < Test::Unit::TestCase
- include AssertEntry
-
- def test_new
- zis = ZipInputStream.new(TestZipFile::TEST_ZIP2.zip_name)
- assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
- zis.close
- end
-
- def test_openWithBlock
- ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) {
- |zis|
- assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
- }
- end
-
- def test_openWithoutBlock
- zis = ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name)
- assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
- end
-
- def test_incompleteReads
- ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) {
- |zis|
- entry = zis.get_next_entry
- assert_equal(TestZipFile::TEST_ZIP2.entry_names[0], entry.name)
- assert zis.gets.length > 0
- entry = zis.get_next_entry
- assert_equal(TestZipFile::TEST_ZIP2.entry_names[1], entry.name)
- assert_equal(0, entry.size)
- assert_equal(nil, zis.gets)
- entry = zis.get_next_entry
- assert_equal(TestZipFile::TEST_ZIP2.entry_names[2], entry.name)
- assert zis.gets.length > 0
- entry = zis.get_next_entry
- assert_equal(TestZipFile::TEST_ZIP2.entry_names[3], entry.name)
- assert zis.gets.length > 0
- }
- end
-
- def test_rewind
- ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) {
- |zis|
- e = zis.get_next_entry
- assert_equal(TestZipFile::TEST_ZIP2.entry_names[0], e.name)
-
- # Do a little reading
- buf = ""
- buf << zis.read(100)
- buf << (zis.gets || "")
- buf << (zis.gets || "")
-
- zis.rewind
-
- buf2 = ""
- buf2 << zis.read(100)
- buf2 << (zis.gets || "")
- buf2 << (zis.gets || "")
-
- assert_equal(buf, buf2)
-
- zis.rewind
-
- assert_entry(e.name, zis, e.name)
- }
- end
-
-end
-
-
-module CrcTest
-
- class TestOutputStream
- include IOExtras::AbstractOutputStream
-
- attr_accessor :buffer
-
- def initialize
- @buffer = ""
- end
-
- def << (data)
- @buffer << data
- self
- end
- end
-
- def run_crc_test(compressorClass)
- str = "Here's a nice little text to compute the crc for! Ho hum, it is nice nice nice nice indeed."
- fakeOut = TestOutputStream.new
-
- deflater = compressorClass.new(fakeOut)
- deflater << str
- assert_equal(0x919920fc, deflater.crc)
- end
-end
-
-
-
-class PassThruCompressorTest < Test::Unit::TestCase
- include CrcTest
-
- def test_size
- File.open("dummy.txt", "wb") {
- |file|
- compressor = PassThruCompressor.new(file)
-
- assert_equal(0, compressor.size)
-
- t1 = "hello world"
- t2 = ""
- t3 = "bingo"
-
- compressor << t1
- assert_equal(compressor.size, t1.size)
-
- compressor << t2
- assert_equal(compressor.size, t1.size + t2.size)
-
- compressor << t3
- assert_equal(compressor.size, t1.size + t2.size + t3.size)
- }
- end
-
- def test_crc
- run_crc_test(PassThruCompressor)
- end
-end
-
-class DeflaterTest < Test::Unit::TestCase
- include CrcTest
-
- def test_outputOperator
- txt = load_file("data/file2.txt")
- deflate(txt, "deflatertest.bin")
- inflatedTxt = inflate("deflatertest.bin")
- assert_equal(txt, inflatedTxt)
- end
-
- private
- def load_file(fileName)
- txt = nil
- File.open(fileName, "rb") { |f| txt = f.read }
- end
-
- def deflate(data, fileName)
- File.open(fileName, "wb") {
- |file|
- deflater = Deflater.new(file)
- deflater << data
- deflater.finish
- assert_equal(deflater.size, data.size)
- file << "trailing data for zlib with -MAX_WBITS"
- }
- end
-
- def inflate(fileName)
- txt = nil
- File.open(fileName, "rb") {
- |file|
- inflater = Inflater.new(file)
- txt = inflater.read
- }
- end
-
- def test_crc
- run_crc_test(Deflater)
- end
-end
-
-class ZipOutputStreamTest < Test::Unit::TestCase
- include AssertEntry
-
- TEST_ZIP = TestZipFile::TEST_ZIP2.clone
- TEST_ZIP.zip_name = "output.zip"
-
- def test_new
- zos = ZipOutputStream.new(TEST_ZIP.zip_name)
- zos.comment = TEST_ZIP.comment
- write_test_zip(zos)
- zos.close
- assert_test_zip_contents(TEST_ZIP)
- end
-
- def test_open
- ZipOutputStream.open(TEST_ZIP.zip_name) {
- |zos|
- zos.comment = TEST_ZIP.comment
- write_test_zip(zos)
- }
- assert_test_zip_contents(TEST_ZIP)
- end
-
- def test_writingToClosedStream
- assert_i_o_error_in_closed_stream { |zos| zos << "hello world" }
- assert_i_o_error_in_closed_stream { |zos| zos.puts "hello world" }
- assert_i_o_error_in_closed_stream { |zos| zos.write "hello world" }
- end
-
- def test_cannotOpenFile
- name = TestFiles::EMPTY_TEST_DIR
- begin
- zos = ZipOutputStream.open(name)
- rescue Exception
- assert($!.kind_of?(Errno::EISDIR) || # Linux
- $!.kind_of?(Errno::EEXIST) || # Windows/cygwin
- $!.kind_of?(Errno::EACCES), # Windows
- "Expected Errno::EISDIR (or on win/cygwin: Errno::EEXIST), but was: #{$!.class}")
- end
- end
-
- def assert_i_o_error_in_closed_stream
- assert_raise(IOError) {
- zos = ZipOutputStream.new("test_putOnClosedStream.zip")
- zos.close
- yield zos
- }
- end
-
- def write_test_zip(zos)
- TEST_ZIP.entry_names.each {
- |entryName|
- zos.put_next_entry(entryName)
- File.open(entryName, "rb") { |f| zos.write(f.read) }
- }
- end
-end
-
-
-
-module Enumerable
- def compare_enumerables(otherEnumerable)
- otherAsArray = otherEnumerable.to_a
- index=0
- each_with_index {
- |element, index|
- return false unless yield(element, otherAsArray[index])
- }
- return index+1 == otherAsArray.size
- end
-end
-
-
-class ZipCentralDirectoryEntryTest < Test::Unit::TestCase
-
- def test_read_from_stream
- File.open("data/testDirectory.bin", "rb") {
- |file|
- entry = ZipEntry.read_c_dir_entry(file)
-
- assert_equal("longAscii.txt", entry.name)
- assert_equal(ZipEntry::DEFLATED, entry.compression_method)
- assert_equal(106490, entry.size)
- assert_equal(3784, entry.compressed_size)
- assert_equal(0xfcd1799c, entry.crc)
- assert_equal("", entry.comment)
-
- entry = ZipEntry.read_c_dir_entry(file)
- assert_equal("empty.txt", entry.name)
- assert_equal(ZipEntry::STORED, entry.compression_method)
- assert_equal(0, entry.size)
- assert_equal(0, entry.compressed_size)
- assert_equal(0x0, entry.crc)
- assert_equal("", entry.comment)
-
- entry = ZipEntry.read_c_dir_entry(file)
- assert_equal("short.txt", entry.name)
- assert_equal(ZipEntry::STORED, entry.compression_method)
- assert_equal(6, entry.size)
- assert_equal(6, entry.compressed_size)
- assert_equal(0xbb76fe69, entry.crc)
- assert_equal("", entry.comment)
-
- entry = ZipEntry.read_c_dir_entry(file)
- assert_equal("longBinary.bin", entry.name)
- assert_equal(ZipEntry::DEFLATED, entry.compression_method)
- assert_equal(1000024, entry.size)
- assert_equal(70847, entry.compressed_size)
- assert_equal(0x10da7d59, entry.crc)
- assert_equal("", entry.comment)
-
- entry = ZipEntry.read_c_dir_entry(file)
- assert_equal(nil, entry)
-# Fields that are not check by this test:
-# version made by 2 bytes
-# version needed to extract 2 bytes
-# general purpose bit flag 2 bytes
-# last mod file time 2 bytes
-# last mod file date 2 bytes
-# compressed size 4 bytes
-# uncompressed size 4 bytes
-# disk number start 2 bytes
-# internal file attributes 2 bytes
-# external file attributes 4 bytes
-# relative offset of local header 4 bytes
-
-# file name (variable size)
-# extra field (variable size)
-# file comment (variable size)
-
- }
- end
-
- def test_ReadEntryFromTruncatedZipFile
- fragment=""
- File.open("data/testDirectory.bin") { |f| fragment = f.read(12) } # cdir entry header is at least 46 bytes
- fragment.extend(IOizeString)
- entry = ZipEntry.new
- entry.read_c_dir_entry(fragment)
- fail "ZipError expected"
- rescue ZipError
- end
-
-end
-
-
-class ZipEntrySetTest < Test::Unit::TestCase
- ZIP_ENTRIES = [
- ZipEntry.new("zipfile.zip", "name1", "comment1"),
- ZipEntry.new("zipfile.zip", "name2", "comment1"),
- ZipEntry.new("zipfile.zip", "name3", "comment1"),
- ZipEntry.new("zipfile.zip", "name4", "comment1"),
- ZipEntry.new("zipfile.zip", "name5", "comment1"),
- ZipEntry.new("zipfile.zip", "name6", "comment1")
- ]
-
- def setup
- @zipEntrySet = ZipEntrySet.new(ZIP_ENTRIES)
- end
-
- def test_include
- assert(@zipEntrySet.include?(ZIP_ENTRIES.first))
- assert(! @zipEntrySet.include?(ZipEntry.new("different.zip", "different", "aComment")))
- end
-
- def test_size
- assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size)
- assert_equal(ZIP_ENTRIES.size, @zipEntrySet.length)
- @zipEntrySet << ZipEntry.new("a", "b", "c")
- assert_equal(ZIP_ENTRIES.size + 1, @zipEntrySet.length)
- end
-
- def test_add
- zes = ZipEntrySet.new
- entry1 = ZipEntry.new("zf.zip", "name1")
- entry2 = ZipEntry.new("zf.zip", "name2")
- zes << entry1
- assert(zes.include?(entry1))
- zes.push(entry2)
- assert(zes.include?(entry2))
- end
-
- def test_delete
- assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size)
- entry = @zipEntrySet.delete(ZIP_ENTRIES.first)
- assert_equal(ZIP_ENTRIES.size - 1, @zipEntrySet.size)
- assert_equal(ZIP_ENTRIES.first, entry)
-
- entry = @zipEntrySet.delete(ZIP_ENTRIES.first)
- assert_equal(ZIP_ENTRIES.size - 1, @zipEntrySet.size)
- assert_nil(entry)
- end
-
- def test_each
- # Tested indirectly via each_with_index
- count = 0
- @zipEntrySet.each_with_index {
- |entry, index|
- assert(ZIP_ENTRIES.include?(entry))
- count = count.succ
- }
- assert_equal(ZIP_ENTRIES.size, count)
- end
-
- def test_entries
- assert_equal(ZIP_ENTRIES.sort, @zipEntrySet.entries.sort)
- end
-
- def test_compound
- newEntry = ZipEntry.new("zf.zip", "new entry", "new entry's comment")
- assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size)
- @zipEntrySet << newEntry
- assert_equal(ZIP_ENTRIES.size + 1, @zipEntrySet.size)
- assert(@zipEntrySet.include?(newEntry))
-
- @zipEntrySet.delete(newEntry)
- assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size)
- end
-
- def test_dup
- copy = @zipEntrySet.dup
- assert_equal(@zipEntrySet, copy)
-
- # demonstrate that this is a deep copy
- copy.entries[0].name = "a totally different name"
- assert(@zipEntrySet != copy)
- end
-
- def test_parent
- entries = [
- ZipEntry.new("zf.zip", "a"),
- ZipEntry.new("zf.zip", "a/"),
- ZipEntry.new("zf.zip", "a/b"),
- ZipEntry.new("zf.zip", "a/b/"),
- ZipEntry.new("zf.zip", "a/b/c"),
- ZipEntry.new("zf.zip", "a/b/c/")
- ]
- entrySet = ZipEntrySet.new(entries)
-
- assert_equal(nil, entrySet.parent(entries[0]))
- assert_equal(nil, entrySet.parent(entries[1]))
- assert_equal(entries[1], entrySet.parent(entries[2]))
- assert_equal(entries[1], entrySet.parent(entries[3]))
- assert_equal(entries[3], entrySet.parent(entries[4]))
- assert_equal(entries[3], entrySet.parent(entries[5]))
- end
-end
-
-
-class ZipCentralDirectoryTest < Test::Unit::TestCase
-
- def test_read_from_stream
- File.open(TestZipFile::TEST_ZIP2.zip_name, "rb") {
- |zipFile|
- cdir = ZipCentralDirectory.read_from_stream(zipFile)
-
- assert_equal(TestZipFile::TEST_ZIP2.entry_names.size, cdir.size)
- assert(cdir.entries.sort.compare_enumerables(TestZipFile::TEST_ZIP2.entry_names.sort) {
- |cdirEntry, testEntryName|
- cdirEntry.name == testEntryName
- })
- assert_equal(TestZipFile::TEST_ZIP2.comment, cdir.comment)
- }
- end
-
- def test_readFromInvalidStream
- File.open("data/file2.txt", "rb") {
- |zipFile|
- cdir = ZipCentralDirectory.new
- cdir.read_from_stream(zipFile)
- }
- fail "ZipError expected!"
- rescue ZipError
- end
-
- def test_ReadFromTruncatedZipFile
- fragment=""
- File.open("data/testDirectory.bin") { |f| fragment = f.read }
- fragment.slice!(12) # removed part of first cdir entry. eocd structure still complete
- fragment.extend(IOizeString)
- entry = ZipCentralDirectory.new
- entry.read_from_stream(fragment)
- fail "ZipError expected"
- rescue ZipError
- end
-
- def test_write_to_stream
- entries = [ ZipEntry.new("file.zip", "flimse", "myComment", "somethingExtra"),
- ZipEntry.new("file.zip", "secondEntryName"),
- ZipEntry.new("file.zip", "lastEntry.txt", "Has a comment too") ]
- cdir = ZipCentralDirectory.new(entries, "my zip comment")
- File.open("cdirtest.bin", "wb") { |f| cdir.write_to_stream(f) }
- cdirReadback = ZipCentralDirectory.new
- File.open("cdirtest.bin", "rb") { |f| cdirReadback.read_from_stream(f) }
-
- assert_equal(cdir.entries.sort, cdirReadback.entries.sort)
- end
-
- def test_equality
- cdir1 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
- "somethingExtra"),
- ZipEntry.new("file.zip", "secondEntryName"),
- ZipEntry.new("file.zip", "lastEntry.txt") ],
- "my zip comment")
- cdir2 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
- "somethingExtra"),
- ZipEntry.new("file.zip", "secondEntryName"),
- ZipEntry.new("file.zip", "lastEntry.txt") ],
- "my zip comment")
- cdir3 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
- "somethingExtra"),
- ZipEntry.new("file.zip", "secondEntryName"),
- ZipEntry.new("file.zip", "lastEntry.txt") ],
- "comment?")
- cdir4 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
- "somethingExtra"),
- ZipEntry.new("file.zip", "lastEntry.txt") ],
- "comment?")
- assert_equal(cdir1, cdir1)
- assert_equal(cdir1, cdir2)
-
- assert(cdir1 != cdir3)
- assert(cdir2 != cdir3)
- assert(cdir2 != cdir3)
- assert(cdir3 != cdir4)
-
- assert(cdir3 != "hello")
- end
-end
-
-
-class BasicZipFileTest < Test::Unit::TestCase
- include AssertEntry
-
- def setup
- @zipFile = ZipFile.new(TestZipFile::TEST_ZIP2.zip_name)
- @testEntryNameIndex=0
- end
-
- def test_entries
- assert_equal(TestZipFile::TEST_ZIP2.entry_names.sort,
- @zipFile.entries.entries.sort.map {|e| e.name} )
- end
-
- def test_each
- count = 0
- visited = {}
- @zipFile.each {
- |entry|
- assert(TestZipFile::TEST_ZIP2.entry_names.include?(entry.name))
- assert(! visited.include?(entry.name))
- visited[entry.name] = nil
- count = count.succ
- }
- assert_equal(TestZipFile::TEST_ZIP2.entry_names.length, count)
- end
-
- def test_foreach
- count = 0
- visited = {}
- ZipFile.foreach(TestZipFile::TEST_ZIP2.zip_name) {
- |entry|
- assert(TestZipFile::TEST_ZIP2.entry_names.include?(entry.name))
- assert(! visited.include?(entry.name))
- visited[entry.name] = nil
- count = count.succ
- }
- assert_equal(TestZipFile::TEST_ZIP2.entry_names.length, count)
- end
-
- def test_get_input_stream
- count = 0
- visited = {}
- @zipFile.each {
- |entry|
- assert_entry(entry.name, @zipFile.get_input_stream(entry), entry.name)
- assert(! visited.include?(entry.name))
- visited[entry.name] = nil
- count = count.succ
- }
- assert_equal(TestZipFile::TEST_ZIP2.entry_names.length, count)
- end
-
- def test_get_input_streamBlock
- fileAndEntryName = @zipFile.entries.first.name
- @zipFile.get_input_stream(fileAndEntryName) {
- |zis|
- assert_entryContentsForStream(fileAndEntryName,
- zis,
- fileAndEntryName)
- }
- end
-end
-
-module CommonZipFileFixture
- include AssertEntry
-
- EMPTY_FILENAME = "emptyZipFile.zip"
-
- TEST_ZIP = TestZipFile::TEST_ZIP2.clone
- TEST_ZIP.zip_name = "4entry_copy.zip"
-
- def setup
- File.delete(EMPTY_FILENAME) if File.exists?(EMPTY_FILENAME)
- File.copy(TestZipFile::TEST_ZIP2.zip_name, TEST_ZIP.zip_name)
- end
-end
-
-class ZipFileTest < Test::Unit::TestCase
- include CommonZipFileFixture
-
- def test_createFromScratch
- comment = "a short comment"
-
- zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE)
- zf.get_output_stream("myFile") { |os| os.write "myFile contains just this" }
- zf.mkdir("dir1")
- zf.comment = comment
- zf.close
-
- zfRead = ZipFile.new(EMPTY_FILENAME)
- assert_equal(comment, zfRead.comment)
- assert_equal(2, zfRead.entries.length)
- end
-
- def test_get_output_stream
- entryCount = nil
- ZipFile.open(TEST_ZIP.zip_name) {
- |zf|
- entryCount = zf.size
- zf.get_output_stream('newEntry.txt') {
- |os|
- os.write "Putting stuff in newEntry.txt"
- }
- assert_equal(entryCount+1, zf.size)
- assert_equal("Putting stuff in newEntry.txt", zf.read("newEntry.txt"))
-
- zf.get_output_stream(zf.get_entry('data/generated/empty.txt')) {
- |os|
- os.write "Putting stuff in data/generated/empty.txt"
- }
- assert_equal(entryCount+1, zf.size)
- assert_equal("Putting stuff in data/generated/empty.txt", zf.read("data/generated/empty.txt"))
-
- }
-
- ZipFile.open(TEST_ZIP.zip_name) {
- |zf|
- assert_equal(entryCount+1, zf.size)
- assert_equal("Putting stuff in newEntry.txt", zf.read("newEntry.txt"))
- assert_equal("Putting stuff in data/generated/empty.txt", zf.read("data/generated/empty.txt"))
- }
- end
-
- def test_add
- srcFile = "data/file2.txt"
- entryName = "newEntryName.rb"
- assert(File.exists?(srcFile))
- zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE)
- zf.add(entryName, srcFile)
- zf.close
-
- zfRead = ZipFile.new(EMPTY_FILENAME)
- assert_equal("", zfRead.comment)
- assert_equal(1, zfRead.entries.length)
- assert_equal(entryName, zfRead.entries.first.name)
- AssertEntry.assert_contents(srcFile,
- zfRead.get_input_stream(entryName) { |zis| zis.read })
- end
-
- def test_addExistingEntryName
- assert_raise(ZipEntryExistsError) {
- ZipFile.open(TEST_ZIP.zip_name) {
- |zf|
- zf.add(zf.entries.first.name, "data/file2.txt")
- }
- }
- end
-
- def test_addExistingEntryNameReplace
- gotCalled = false
- replacedEntry = nil
- ZipFile.open(TEST_ZIP.zip_name) {
- |zf|
- replacedEntry = zf.entries.first.name
- zf.add(replacedEntry, "data/file2.txt") { gotCalled = true; true }
- }
- assert(gotCalled)
- ZipFile.open(TEST_ZIP.zip_name) {
- |zf|
- assert_contains(zf, replacedEntry, "data/file2.txt")
- }
- end
-
- def test_addDirectory
- ZipFile.open(TEST_ZIP.zip_name) {
- |zf|
- zf.add(TestFiles::EMPTY_TEST_DIR, TestFiles::EMPTY_TEST_DIR)
- }
- ZipFile.open(TEST_ZIP.zip_name) {
- |zf|
- dirEntry = zf.entries.detect { |e| e.name == TestFiles::EMPTY_TEST_DIR+"/" }
- assert(dirEntry.is_directory)
- }
- end
-
- def test_remove
- entryToRemove, *remainingEntries = TEST_ZIP.entry_names
-
- File.copy(TestZipFile::TEST_ZIP2.zip_name, TEST_ZIP.zip_name)
-
- zf = ZipFile.new(TEST_ZIP.zip_name)
- assert(zf.entries.map { |e| e.name }.include?(entryToRemove))
- zf.remove(entryToRemove)
- assert(! zf.entries.map { |e| e.name }.include?(entryToRemove))
- assert_equal(zf.entries.map {|x| x.name }.sort, remainingEntries.sort)
- zf.close
-
- zfRead = ZipFile.new(TEST_ZIP.zip_name)
- assert(! zfRead.entries.map { |e| e.name }.include?(entryToRemove))
- assert_equal(zfRead.entries.map {|x| x.name }.sort, remainingEntries.sort)
- zfRead.close
- end
-
-
- def test_rename
- entryToRename, *remainingEntries = TEST_ZIP.entry_names
-
- zf = ZipFile.new(TEST_ZIP.zip_name)
- assert(zf.entries.map { |e| e.name }.include?(entryToRename))
-
- newName = "changed name"
- assert(! zf.entries.map { |e| e.name }.include?(newName))
-
- zf.rename(entryToRename, newName)
- assert(zf.entries.map { |e| e.name }.include?(newName))
-
- zf.close
-
- zfRead = ZipFile.new(TEST_ZIP.zip_name)
- assert(zfRead.entries.map { |e| e.name }.include?(newName))
- zfRead.close
- end
-
- def test_renameToExistingEntry
- oldEntries = nil
- ZipFile.open(TEST_ZIP.zip_name) { |zf| oldEntries = zf.entries }
-
- assert_raise(ZipEntryExistsError) {
- ZipFile.open(TEST_ZIP.zip_name) {
- |zf|
- zf.rename(zf.entries[0], zf.entries[1].name)
- }
- }
-
- ZipFile.open(TEST_ZIP.zip_name) {
- |zf|
- assert_equal(oldEntries.sort.map{ |e| e.name }, zf.entries.sort.map{ |e| e.name })
- }
- end
-
- def test_renameToExistingEntryOverwrite
- oldEntries = nil
- ZipFile.open(TEST_ZIP.zip_name) { |zf| oldEntries = zf.entries }
-
- gotCalled = false
- renamedEntryName = nil
- ZipFile.open(TEST_ZIP.zip_name) {
- |zf|
- renamedEntryName = zf.entries[0].name
- zf.rename(zf.entries[0], zf.entries[1].name) { gotCalled = true; true }
- }
-
- assert(gotCalled)
- oldEntries.delete_if { |e| e.name == renamedEntryName }
- ZipFile.open(TEST_ZIP.zip_name) {
- |zf|
- assert_equal(oldEntries.sort.map{ |e| e.name },
- zf.entries.sort.map{ |e| e.name })
- }
- end
-
- def test_renameNonEntry
- nonEntry = "bogusEntry"
- target_entry = "target_entryName"
- zf = ZipFile.new(TEST_ZIP.zip_name)
- assert(! zf.entries.include?(nonEntry))
- assert_raise(Errno::ENOENT) {
- zf.rename(nonEntry, target_entry)
- }
- zf.commit
- assert(! zf.entries.include?(target_entry))
- ensure
- zf.close
- end
-
- def test_renameEntryToExistingEntry
- entry1, entry2, *remaining = TEST_ZIP.entry_names
- zf = ZipFile.new(TEST_ZIP.zip_name)
- assert_raise(ZipEntryExistsError) {
- zf.rename(entry1, entry2)
- }
- ensure
- zf.close
- end
-
- def test_replace
- entryToReplace = TEST_ZIP.entry_names[2]
- newEntrySrcFilename = "data/file2.txt"
- zf = ZipFile.new(TEST_ZIP.zip_name)
- zf.replace(entryToReplace, newEntrySrcFilename)
-
- zf.close
- zfRead = ZipFile.new(TEST_ZIP.zip_name)
- AssertEntry::assert_contents(newEntrySrcFilename,
- zfRead.get_input_stream(entryToReplace) { |is| is.read })
- AssertEntry::assert_contents(TEST_ZIP.entry_names[0],
- zfRead.get_input_stream(TEST_ZIP.entry_names[0]) { |is| is.read })
- AssertEntry::assert_contents(TEST_ZIP.entry_names[1],
- zfRead.get_input_stream(TEST_ZIP.entry_names[1]) { |is| is.read })
- AssertEntry::assert_contents(TEST_ZIP.entry_names[3],
- zfRead.get_input_stream(TEST_ZIP.entry_names[3]) { |is| is.read })
- zfRead.close
- end
-
- def test_replaceNonEntry
- entryToReplace = "nonExistingEntryname"
- ZipFile.open(TEST_ZIP.zip_name) {
- |zf|
- assert_raise(Errno::ENOENT) {
- zf.replace(entryToReplace, "data/file2.txt")
- }
- }
- end
-
- def test_commit
- newName = "renamedFirst"
- zf = ZipFile.new(TEST_ZIP.zip_name)
- oldName = zf.entries.first
- zf.rename(oldName, newName)
- zf.commit
-
- zfRead = ZipFile.new(TEST_ZIP.zip_name)
- assert(zfRead.entries.detect { |e| e.name == newName } != nil)
- assert(zfRead.entries.detect { |e| e.name == oldName } == nil)
- zfRead.close
-
- zf.close
- end
-
- # This test tests that after commit, you
- # can delete the file you used to add the entry to the zip file
- # with
- def test_commitUseZipEntry
- File.copy(TestFiles::RANDOM_ASCII_FILE1, "okToDelete.txt")
- zf = ZipFile.open(TEST_ZIP.zip_name)
- zf.add("okToDelete.txt", "okToDelete.txt")
- assert_contains(zf, "okToDelete.txt")
- zf.commit
- File.move("okToDelete.txt", "okToDeleteMoved.txt")
- assert_contains(zf, "okToDelete.txt", "okToDeleteMoved.txt")
- end
-
-# def test_close
-# zf = ZipFile.new(TEST_ZIP.zip_name)
-# zf.close
-# assert_raise(IOError) {
-# zf.extract(TEST_ZIP.entry_names.first, "hullubullu")
-# }
-# end
-
- def test_compound1
- renamedName = "renamedName"
- originalEntries = []
- begin
- zf = ZipFile.new(TEST_ZIP.zip_name)
- originalEntries = zf.entries.dup
-
- assert_not_contains(zf, TestFiles::RANDOM_ASCII_FILE1)
- zf.add(TestFiles::RANDOM_ASCII_FILE1,
- TestFiles::RANDOM_ASCII_FILE1)
- assert_contains(zf, TestFiles::RANDOM_ASCII_FILE1)
-
- zf.rename(zf.entries[0], renamedName)
- assert_contains(zf, renamedName)
-
- TestFiles::BINARY_TEST_FILES.each {
- |filename|
- zf.add(filename, filename)
- assert_contains(zf, filename)
- }
-
- assert_contains(zf, originalEntries.last.to_s)
- zf.remove(originalEntries.last.to_s)
- assert_not_contains(zf, originalEntries.last.to_s)
-
- ensure
- zf.close
- end
- begin
- zfRead = ZipFile.new(TEST_ZIP.zip_name)
- assert_contains(zfRead, TestFiles::RANDOM_ASCII_FILE1)
- assert_contains(zfRead, renamedName)
- TestFiles::BINARY_TEST_FILES.each {
- |filename|
- assert_contains(zfRead, filename)
- }
- assert_not_contains(zfRead, originalEntries.last.to_s)
- ensure
- zfRead.close
- end
- end
-
- def test_compound2
- begin
- zf = ZipFile.new(TEST_ZIP.zip_name)
- originalEntries = zf.entries.dup
-
- originalEntries.each {
- |entry|
- zf.remove(entry)
- assert_not_contains(zf, entry)
- }
- assert(zf.entries.empty?)
-
- TestFiles::ASCII_TEST_FILES.each {
- |filename|
- zf.add(filename, filename)
- assert_contains(zf, filename)
- }
- assert_equal(zf.entries.sort.map { |e| e.name }, TestFiles::ASCII_TEST_FILES)
-
- zf.rename(TestFiles::ASCII_TEST_FILES[0], "newName")
- assert_not_contains(zf, TestFiles::ASCII_TEST_FILES[0])
- assert_contains(zf, "newName")
- ensure
- zf.close
- end
- begin
- zfRead = ZipFile.new(TEST_ZIP.zip_name)
- asciiTestFiles = TestFiles::ASCII_TEST_FILES.dup
- asciiTestFiles.shift
- asciiTestFiles.each {
- |filename|
- assert_contains(zf, filename)
- }
-
- assert_contains(zf, "newName")
- ensure
- zfRead.close
- end
- end
-
- private
- def assert_contains(zf, entryName, filename = entryName)
- assert(zf.entries.detect { |e| e.name == entryName} != nil, "entry #{entryName} not in #{zf.entries.join(', ')} in zip file #{zf}")
- assert_entryContents(zf, entryName, filename) if File.exists?(filename)
- end
-
- def assert_not_contains(zf, entryName)
- assert(zf.entries.detect { |e| e.name == entryName} == nil, "entry #{entryName} in #{zf.entries.join(', ')} in zip file #{zf}")
- end
-end
-
-class ZipFileExtractTest < Test::Unit::TestCase
- include CommonZipFileFixture
- EXTRACTED_FILENAME = "extEntry"
- ENTRY_TO_EXTRACT, *REMAINING_ENTRIES = TEST_ZIP.entry_names.reverse
-
- def setup
- super
- File.delete(EXTRACTED_FILENAME) if File.exists?(EXTRACTED_FILENAME)
- end
-
- def test_extract
- ZipFile.open(TEST_ZIP.zip_name) {
- |zf|
- zf.extract(ENTRY_TO_EXTRACT, EXTRACTED_FILENAME)
-
- assert(File.exists?(EXTRACTED_FILENAME))
- AssertEntry::assert_contents(EXTRACTED_FILENAME,
- zf.get_input_stream(ENTRY_TO_EXTRACT) { |is| is.read })
- }
- end
-
- def test_extractExists
- writtenText = "written text"
- File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) }
-
- assert_raise(ZipDestinationFileExistsError) {
- ZipFile.open(TEST_ZIP.zip_name) {
- |zf|
- zf.extract(zf.entries.first, EXTRACTED_FILENAME)
- }
- }
- File.open(EXTRACTED_FILENAME, "r") {
- |f|
- assert_equal(writtenText, f.read)
- }
- end
-
- def test_extractExistsOverwrite
- writtenText = "written text"
- File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) }
-
- gotCalledCorrectly = false
- ZipFile.open(TEST_ZIP.zip_name) {
- |zf|
- zf.extract(zf.entries.first, EXTRACTED_FILENAME) {
- |entry, extractLoc|
- gotCalledCorrectly = zf.entries.first == entry &&
- extractLoc == EXTRACTED_FILENAME
- true
- }
- }
-
- assert(gotCalledCorrectly)
- File.open(EXTRACTED_FILENAME, "r") {
- |f|
- assert(writtenText != f.read)
- }
- end
-
- def test_extractNonEntry
- zf = ZipFile.new(TEST_ZIP.zip_name)
- assert_raise(Errno::ENOENT) { zf.extract("nonExistingEntry", "nonExistingEntry") }
- ensure
- zf.close if zf
- end
-
- def test_extractNonEntry2
- outFile = "outfile"
- assert_raise(Errno::ENOENT) {
- zf = ZipFile.new(TEST_ZIP.zip_name)
- nonEntry = "hotdog-diddelidoo"
- assert(! zf.entries.include?(nonEntry))
- zf.extract(nonEntry, outFile)
- zf.close
- }
- assert(! File.exists?(outFile))
- end
-
-end
-
-class ZipFileExtractDirectoryTest < Test::Unit::TestCase
- include CommonZipFileFixture
- TEST_OUT_NAME = "emptyOutDir"
-
- def open_zip(&aProc)
- assert(aProc != nil)
- ZipFile.open(TestZipFile::TEST_ZIP4.zip_name, &aProc)
- end
-
- def extract_test_dir(&aProc)
- open_zip {
- |zf|
- zf.extract(TestFiles::EMPTY_TEST_DIR, TEST_OUT_NAME, &aProc)
- }
- end
-
- def setup
- super
-
- Dir.rmdir(TEST_OUT_NAME) if File.directory? TEST_OUT_NAME
- File.delete(TEST_OUT_NAME) if File.exists? TEST_OUT_NAME
- end
-
- def test_extractDirectory
- extract_test_dir
- assert(File.directory?(TEST_OUT_NAME))
- end
-
- def test_extractDirectoryExistsAsDir
- Dir.mkdir TEST_OUT_NAME
- extract_test_dir
- assert(File.directory?(TEST_OUT_NAME))
- end
-
- def test_extractDirectoryExistsAsFile
- File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" }
- assert_raise(ZipDestinationFileExistsError) { extract_test_dir }
- end
-
- def test_extractDirectoryExistsAsFileOverwrite
- File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" }
- gotCalled = false
- extract_test_dir {
- |entry, destPath|
- gotCalled = true
- assert_equal(TEST_OUT_NAME, destPath)
- assert(entry.is_directory)
- true
- }
- assert(gotCalled)
- assert(File.directory?(TEST_OUT_NAME))
- end
-end
-
-class ZipStreamableFileTest < Test::Unit::TestCase
- def test_equality
- zipEntry1 = ZipEntry.new("zf.zip", "entryname1", "comment")
- zipEntry2 = ZipEntry.new("zf.zip", "entryname2", "comment")
-
- zipStreamableFile1 = ZipStreamableFile.new(zipEntry1, "path")
- zipStreamableFile2 = ZipStreamableFile.new(zipEntry1, "path")
- zipStreamableFile3 = ZipStreamableFile.new(zipEntry1, "anotherPath")
- zipStreamableFile4 = ZipStreamableFile.new(zipEntry2, "path")
-
- assert_equal(zipStreamableFile1, zipStreamableFile1)
- assert_equal(zipStreamableFile1, zipStreamableFile2)
- assert(zipStreamableFile1 != zipStreamableFile3)
- assert(zipStreamableFile1 != zipStreamableFile4)
- assert(zipStreamableFile1 != zipEntry1)
- assert(zipStreamableFile1 != "hej")
- end
-end
-
-class ZipExtraFieldTest < Test::Unit::TestCase
- def test_new
- extra_pure = ZipExtraField.new("")
- extra_withstr = ZipExtraField.new("foo")
- assert_instance_of(ZipExtraField, extra_pure)
- assert_instance_of(ZipExtraField, extra_withstr)
- end
-
- def test_unknownfield
- extra = ZipExtraField.new("foo")
- assert_equal(extra["Unknown"], "foo")
- extra.merge("a")
- assert_equal(extra["Unknown"], "fooa")
- extra.merge("barbaz")
- assert_equal(extra.to_s, "fooabarbaz")
- end
-
-
- def test_merge
- str = "UT\x5\0\x3\250$\r@Ux\0\0"
- extra1 = ZipExtraField.new("")
- extra2 = ZipExtraField.new(str)
- assert(! extra1.member?("UniversalTime"))
- assert(extra2.member?("UniversalTime"))
- extra1.merge(str)
- assert_equal(extra1["UniversalTime"].mtime, extra2["UniversalTime"].mtime)
- end
-
- def test_length
- str = "UT\x5\0\x3\250$\r@Ux\0\0Te\0\0testit"
- extra = ZipExtraField.new(str)
- assert_equal(extra.local_length, extra.to_local_bin.length)
- assert_equal(extra.c_dir_length, extra.to_c_dir_bin.length)
- extra.merge("foo")
- assert_equal(extra.local_length, extra.to_local_bin.length)
- assert_equal(extra.c_dir_length, extra.to_c_dir_bin.length)
- end
-
-
- def test_to_s
- str = "UT\x5\0\x3\250$\r@Ux\0\0Te\0\0testit"
- extra = ZipExtraField.new(str)
- assert_instance_of(String, extra.to_s)
-
- s = extra.to_s
- extra.merge("foo")
- assert_equal(s.length + 3, extra.to_s.length)
- end
-
- def test_equality
- str = "UT\x5\0\x3\250$\r@"
- extra1 = ZipExtraField.new(str)
- extra2 = ZipExtraField.new(str)
- extra3 = ZipExtraField.new(str)
- assert_equal(extra1, extra2)
-
- extra2["UniversalTime"].mtime = Time.now
- assert(extra1 != extra2)
-
- extra3.create("IUnix")
- assert(extra1 != extra3)
-
- extra1.create("IUnix")
- assert_equal(extra1, extra3)
- end
-
-end
-
-# Copyright (C) 2002, 2003 Thomas Sondergaard
-# rubyzip is free software; you can redistribute it and/or
-# modify it under the terms of the ruby license.
From c6ea47d6deeec7e4d44f419352bd69ba710e137f Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Wed, 2 Nov 2005 05:36:11 +0000
Subject: [PATCH 77/84] Dropping .erbsql files (we now have schema.rb instead)
---
db/pages.erbsql | 9 --------
db/revisions.erbsql | 16 ---------------
db/schema.postgre.sql | 43 ---------------------------------------
db/system.erbsql | 4 ----
db/webs.erbsql | 17 ----------------
db/wiki_references.erbsql | 9 --------
6 files changed, 98 deletions(-)
delete mode 100644 db/pages.erbsql
delete mode 100644 db/revisions.erbsql
delete mode 100644 db/schema.postgre.sql
delete mode 100644 db/system.erbsql
delete mode 100644 db/webs.erbsql
delete mode 100644 db/wiki_references.erbsql
diff --git a/db/pages.erbsql b/db/pages.erbsql
deleted file mode 100644
index 5c2dd6d5..00000000
--- a/db/pages.erbsql
+++ /dev/null
@@ -1,9 +0,0 @@
-CREATE TABLE pages (
- id <%= @pk %>,
- created_at <%= @datetime %> NOT NULL,
- updated_at <%= @datetime %> NOT NULL,
- web_id INTEGER NOT NULL,
- locked_by VARCHAR(60),
- name VARCHAR(60),
- locked_at <%= @datetime %>
-) <%= create_options %>;
\ No newline at end of file
diff --git a/db/revisions.erbsql b/db/revisions.erbsql
deleted file mode 100644
index 2b8e6e0e..00000000
--- a/db/revisions.erbsql
+++ /dev/null
@@ -1,16 +0,0 @@
-CREATE TABLE revisions (
- id <%= @pk %>,
- created_at <%= @datetime %> NOT NULL,
- updated_at <%= @datetime %> NOT NULL,
-
- -- note that continuous edits change the existing last revision, instead of creating one
- -- revised_at is the timestamp of last edit of this revision
- -- unlike updated_at is can be set explicitly in a call to Revision.create
- -- besides, it should not be updated when Revision row changes for any other reason than
- -- changing content
- revised_at <%= @datetime %> NOT NULL,
- page_id INTEGER NOT NULL,
- content TEXT NOT NULL,
- author VARCHAR(60),
- ip VARCHAR(60)
-) <%= create_options %>;
\ No newline at end of file
diff --git a/db/schema.postgre.sql b/db/schema.postgre.sql
deleted file mode 100644
index 5191d9e4..00000000
--- a/db/schema.postgre.sql
+++ /dev/null
@@ -1,43 +0,0 @@
-CREATE TABLE pages (
- id serial primary key,
- created_at timestamp without time zone NOT NULL,
- updated_at timestamp without time zone NOT NULL,
- web_id integer NOT NULL,
- locked_by character varying(60),
- name character varying(60),
- locked_at timestamp without time zone
-);
-
-CREATE TABLE revisions (
- id serial primary key,
- created_at timestamp without time zone NOT NULL,
- updated_at timestamp without time zone NOT NULL,
- page_id integer NOT NULL,
- content text NOT NULL,
- author character varying(60),
- ip character varying(60),
- number integer
-);
-
-CREATE TABLE system (
- id serial primary key,
- "password" character varying(60)
-);
-
-CREATE TABLE webs (
- id serial primary key,
- created_at timestamp without time zone NOT NULL,
- updated_at timestamp without time zone NOT NULL,
- name character varying(60) NOT NULL,
- address character varying(60) NOT NULL,
- "password" character varying(60),
- additional_style character varying(255),
- allow_uploads boolean DEFAULT true,
- published boolean DEFAULT false,
- count_pages boolean DEFAULT false,
- markup character varying(50) DEFAULT 'textile'::character varying,
- color character varying(6) DEFAULT '008B26'::character varying,
- max_upload_size integer DEFAULT 100,
- safe_mode boolean DEFAULT false,
- brackets_only boolean DEFAULT false
-);
diff --git a/db/system.erbsql b/db/system.erbsql
deleted file mode 100644
index e0a55a33..00000000
--- a/db/system.erbsql
+++ /dev/null
@@ -1,4 +0,0 @@
-CREATE TABLE system (
- id <%= @pk %>,
- <%= db_quote('password') %> VARCHAR(60)
-) <%= create_options %>;
\ No newline at end of file
diff --git a/db/webs.erbsql b/db/webs.erbsql
deleted file mode 100644
index c29728cd..00000000
--- a/db/webs.erbsql
+++ /dev/null
@@ -1,17 +0,0 @@
-CREATE TABLE webs (
- id <%= @pk %>,
- created_at <%= @datetime %> NOT NULL,
- updated_at <%= @datetime %> NOT NULL,
- name VARCHAR(60) NOT NULL,
- address VARCHAR(60) NOT NULL,
- <%= db_quote('password') %> VARCHAR(60),
- additional_style VARCHAR(255),
- allow_uploads <%= @boolean %> DEFAULT '1',
- published <%= @boolean %> DEFAULT '0',
- count_pages <%= @boolean %> DEFAULT '0',
- markup VARCHAR(50) DEFAULT 'textile',
- color VARCHAR(6) DEFAULT '008B26',
- max_upload_size INTEGER DEFAULT 100,
- safe_mode <%= @boolean %> DEFAULT '0',
- brackets_only <%= @boolean %> DEFAULT '0'
-) <%= create_options %>;
\ No newline at end of file
diff --git a/db/wiki_references.erbsql b/db/wiki_references.erbsql
deleted file mode 100644
index 6b7115ce..00000000
--- a/db/wiki_references.erbsql
+++ /dev/null
@@ -1,9 +0,0 @@
-CREATE TABLE wiki_references (
- id <%= @pk %>,
- created_at <%= @datetime %> NOT NULL,
- updated_at <%= @datetime %> NOT NULL,
-
- page_id INTEGER NOT NULL,
- referenced_name VARCHAR(60) NOT NULL,
- link_type CHAR(1) NOT NULL
-) <%= create_options %>;
\ No newline at end of file
From 26a5338764d46c31275d3df138c4cef9a56407be Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Wed, 2 Nov 2005 05:59:49 +0000
Subject: [PATCH 78/84] FIX BUILD
---
config/environment.rb | 3 ---
test/functional/file_controller_test.rb | 1 +
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/config/environment.rb b/config/environment.rb
index 4d19868a..19c69a79 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -16,9 +16,6 @@ Rails::Initializer.run do |config|
# Activate observers that should always be running
# config.active_record.observers = :cacher, :garbage_collector
- # Make Active Record use UTC-base instead of local time
- config.active_record.default_timezone = :utc
-
# Use Active Record's schema dumper instead of SQL when creating the test database
# (enables use of different database adapters for development and test environments)
config.active_record.schema_format = :ruby
diff --git a/test/functional/file_controller_test.rb b/test/functional/file_controller_test.rb
index 102ff8d5..24fc2125 100755
--- a/test/functional/file_controller_test.rb
+++ b/test/functional/file_controller_test.rb
@@ -3,6 +3,7 @@
require File.dirname(__FILE__) + '/../test_helper'
require 'file_controller'
require 'fileutils'
+require 'stringio'
# Raise errors beyond the default web-based presentation
class FileController; def rescue_action(e) logger.error(e); raise e end; end
From 7f8d3adfb5421e0164f4aebf906e6aedf7c3d257 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Wed, 2 Nov 2005 07:34:11 +0000
Subject: [PATCH 79/84] Copied over 0.14.2 ./public contents
---
app/controllers/application.rb | 2 -
config/environment.rb | 2 +-
db/schema.rb | 8 +
public/.htaccess | 12 +-
public/dispatch.cgi | 18 +-
public/dispatch.fcgi | 48 +-
public/dispatch.rb | 2 +-
public/javascripts/controls.js | 1154 ++++++-----
public/javascripts/dragdrop.js | 1053 +++++-----
public/javascripts/effects.js | 1713 +++++++++++------
public/javascripts/prototype.js | 2762 +++++++++++++++++----------
public/javascripts/scriptaculous.js | 47 +
public/javascripts/slider.js | 258 +++
public/robots.txt | 1 +
14 files changed, 4408 insertions(+), 2672 deletions(-)
create mode 100644 public/javascripts/scriptaculous.js
create mode 100644 public/javascripts/slider.js
create mode 100644 public/robots.txt
diff --git a/app/controllers/application.rb b/app/controllers/application.rb
index 9306b9c3..9a601b72 100644
--- a/app/controllers/application.rb
+++ b/app/controllers/application.rb
@@ -5,8 +5,6 @@ class ApplicationController < ActionController::Base
before_filter :connect_to_model, :setup_url_generator, :set_content_type_header, :set_robots_metatag
after_filter :remember_location, :teardown_url_generator
- observer :page_observer
-
# For injecting a different wiki model implementation. Intended for use in tests
def self.wiki=(the_wiki)
# a global variable is used here because Rails reloads controller and model classes in the
diff --git a/config/environment.rb b/config/environment.rb
index 19c69a79..cb7c9b42 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -14,7 +14,7 @@ Rails::Initializer.run do |config|
# config.action_controller.fragment_cache_store = :file_store, "#{RAILS_ROOT}/cache"
# Activate observers that should always be running
- # config.active_record.observers = :cacher, :garbage_collector
+ config.active_record.observers = :page_observer
# Use Active Record's schema dumper instead of SQL when creating the test database
# (enables use of different database adapters for development and test environments)
diff --git a/db/schema.rb b/db/schema.rb
index 4eb50fdf..1bf4af3a 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -23,6 +23,14 @@ ActiveRecord::Schema.define() do
t.column "ip", :string, :limit => 60
end
+ create_table "sessions", :force => true do |t|
+ t.column "session_id", :string
+ t.column "data", :text
+ t.column "updated_at", :datetime
+ end
+
+ add_index "sessions", ["session_id"], :name => "sessions_session_id_index"
+
create_table "system", :force => true do |t|
t.column "password", :string, :limit => 60
end
diff --git a/public/.htaccess b/public/.htaccess
index 7eb56e8b..d3c99834 100644
--- a/public/.htaccess
+++ b/public/.htaccess
@@ -18,10 +18,18 @@ Options +FollowSymLinks +ExecCGI
# Example:
# RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
RewriteEngine On
+
+# If your Rails application is accessed via an Alias directive,
+# then you MUST also set the RewriteBase in this htaccess file.
+#
+# Example:
+# Alias /myrailsapp /path/to/myrailsapp/public
+# RewriteBase /myrailsapp
+
RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
-RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
+RewriteRule ^(.*)$ dispatch.cgi [QSA,L]
# In case Rails experiences terminal errors
# Instead of displaying this message you can supply a file here which will be rendered instead
@@ -29,4 +37,4 @@ RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
# Example:
# ErrorDocument 500 /500.html
-ErrorDocument 500 "
Application error
Rails application failed to start properly"
+ErrorDocument 500 "
Application error
Rails application failed to start properly"
\ No newline at end of file
diff --git a/public/dispatch.cgi b/public/dispatch.cgi
index ce705d36..d89311e3 100755
--- a/public/dispatch.cgi
+++ b/public/dispatch.cgi
@@ -1,10 +1,10 @@
-#!/usr/bin/env ruby
-
-require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
-
-# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
-# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
-require "dispatcher"
-
-ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
+#!c:/ruby/bin/ruby
+
+require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
+
+# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
+# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
+require "dispatcher"
+
+ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
Dispatcher.dispatch
\ No newline at end of file
diff --git a/public/dispatch.fcgi b/public/dispatch.fcgi
index 664dbbbe..cc87e0bd 100755
--- a/public/dispatch.fcgi
+++ b/public/dispatch.fcgi
@@ -1,24 +1,24 @@
-#!/usr/bin/env ruby
-#
-# You may specify the path to the FastCGI crash log (a log of unhandled
-# exceptions which forced the FastCGI instance to exit, great for debugging)
-# and the number of requests to process before running garbage collection.
-#
-# By default, the FastCGI crash log is RAILS_ROOT/log/fastcgi.crash.log
-# and the GC period is nil (turned off). A reasonable number of requests
-# could range from 10-100 depending on the memory footprint of your app.
-#
-# Example:
-# # Default log path, normal GC behavior.
-# RailsFCGIHandler.process!
-#
-# # Default log path, 50 requests between GC.
-# RailsFCGIHandler.process! nil, 50
-#
-# # Custom log path, normal GC behavior.
-# RailsFCGIHandler.process! '/var/log/myapp_fcgi_crash.log'
-#
-require File.dirname(__FILE__) + "/../config/environment"
-require 'fcgi_handler'
-
-RailsFCGIHandler.process!
+#!c:/ruby/bin/ruby
+#
+# You may specify the path to the FastCGI crash log (a log of unhandled
+# exceptions which forced the FastCGI instance to exit, great for debugging)
+# and the number of requests to process before running garbage collection.
+#
+# By default, the FastCGI crash log is RAILS_ROOT/log/fastcgi.crash.log
+# and the GC period is nil (turned off). A reasonable number of requests
+# could range from 10-100 depending on the memory footprint of your app.
+#
+# Example:
+# # Default log path, normal GC behavior.
+# RailsFCGIHandler.process!
+#
+# # Default log path, 50 requests between GC.
+# RailsFCGIHandler.process! nil, 50
+#
+# # Custom log path, normal GC behavior.
+# RailsFCGIHandler.process! '/var/log/myapp_fcgi_crash.log'
+#
+require File.dirname(__FILE__) + "/../config/environment"
+require 'fcgi_handler'
+
+RailsFCGIHandler.process!
diff --git a/public/dispatch.rb b/public/dispatch.rb
index ce705d36..c584d668 100755
--- a/public/dispatch.rb
+++ b/public/dispatch.rb
@@ -1,4 +1,4 @@
-#!/usr/bin/env ruby
+#!c:/ruby/bin/ruby
require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
diff --git a/public/javascripts/controls.js b/public/javascripts/controls.js
index cece0a91..b9ce4727 100644
--- a/public/javascripts/controls.js
+++ b/public/javascripts/controls.js
@@ -1,446 +1,708 @@
-// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Element.collectTextNodesIgnoreClass = function(element, ignoreclass) {
- var children = $(element).childNodes;
- var text = "";
- var classtest = new RegExp("^([^ ]+ )*" + ignoreclass+ "( [^ ]+)*$","i");
-
- for (var i = 0; i < children.length; i++) {
- if(children[i].nodeType==3) {
- text+=children[i].nodeValue;
- } else {
- if((!children[i].className.match(classtest)) && children[i].hasChildNodes())
- text += Element.collectTextNodesIgnoreClass(children[i], ignoreclass);
- }
- }
-
- return text;
-}
-
-// Autocompleter.Base handles all the autocompletion functionality
-// that's independent of the data source for autocompletion. This
-// includes drawing the autocompletion menu, observing keyboard
-// and mouse events, and similar.
-//
-// Specific autocompleters need to provide, at the very least,
-// a getUpdatedChoices function that will be invoked every time
-// the text inside the monitored textbox changes. This method
-// should get the text for which to provide autocompletion by
-// invoking this.getEntry(), NOT by directly accessing
-// this.element.value. This is to allow incremental tokenized
-// autocompletion. Specific auto-completion logic (AJAX, etc)
-// belongs in getUpdatedChoices.
-//
-// Tokenized incremental autocompletion is enabled automatically
-// when an autocompleter is instantiated with the 'tokens' option
-// in the options parameter, e.g.:
-// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
-// will incrementally autocomplete with a comma as the token.
-// Additionally, ',' in the above example can be replaced with
-// a token array, e.g. { tokens: new Array (',', '\n') } which
-// enables autocompletion on multiple tokens. This is most
-// useful when one of the tokens is \n (a newline), as it
-// allows smart autocompletion after linebreaks.
-
-var Autocompleter = {}
-Autocompleter.Base = function() {};
-Autocompleter.Base.prototype = {
- base_initialize: function(element, update, options) {
- this.element = $(element);
- this.update = $(update);
- this.has_focus = false;
- this.changed = false;
- this.active = false;
- this.index = 0;
- this.entry_count = 0;
-
- if (this.setOptions)
- this.setOptions(options);
- else
- this.options = {}
-
- this.options.tokens = this.options.tokens || new Array();
- this.options.frequency = this.options.frequency || 0.4;
- this.options.min_chars = this.options.min_chars || 1;
- this.options.onShow = this.options.onShow ||
- function(element, update){
- if(!update.style.position || update.style.position=='absolute') {
- update.style.position = 'absolute';
- var offsets = Position.cumulativeOffset(element);
- update.style.left = offsets[0] + 'px';
- update.style.top = (offsets[1] + element.offsetHeight) + 'px';
- update.style.width = element.offsetWidth + 'px';
- }
- new Effect.Appear(update,{duration:0.15});
- };
- this.options.onHide = this.options.onHide ||
- function(element, update){ new Effect.Fade(update,{duration:0.15}) };
-
- if(this.options.indicator)
- this.indicator = $(this.options.indicator);
-
- if (typeof(this.options.tokens) == 'string')
- this.options.tokens = new Array(this.options.tokens);
-
- this.observer = null;
-
- Element.hide(this.update);
-
- Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
- Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));
- },
-
- show: function() {
- if(this.update.style.display=='none') this.options.onShow(this.element, this.update);
- if(!this.iefix && (navigator.appVersion.indexOf('MSIE')>0) && this.update.style.position=='absolute') {
- new Insertion.After(this.update,
- '');
- this.iefix = $(this.update.id+'_iefix');
- }
- if(this.iefix) {
- Position.clone(this.update, this.iefix);
- this.iefix.style.zIndex = 1;
- this.update.style.zIndex = 2;
- Element.show(this.iefix);
- }
- },
-
- hide: function() {
- if(this.update.style.display=='') this.options.onHide(this.element, this.update);
- if(this.iefix) Element.hide(this.iefix);
- },
-
- startIndicator: function() {
- if(this.indicator) Element.show(this.indicator);
- },
-
- stopIndicator: function() {
- if(this.indicator) Element.hide(this.indicator);
- },
-
- onKeyPress: function(event) {
- if(this.active)
- switch(event.keyCode) {
- case Event.KEY_TAB:
- case Event.KEY_RETURN:
- this.select_entry();
- Event.stop(event);
- case Event.KEY_ESC:
- this.hide();
- this.active = false;
- return;
- case Event.KEY_LEFT:
- case Event.KEY_RIGHT:
- return;
- case Event.KEY_UP:
- this.mark_previous();
- this.render();
- if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
- return;
- case Event.KEY_DOWN:
- this.mark_next();
- this.render();
- if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
- return;
- }
- else
- if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN)
- return;
-
- this.changed = true;
- this.has_focus = true;
-
- if(this.observer) clearTimeout(this.observer);
- this.observer =
- setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
- },
-
- onHover: function(event) {
- var element = Event.findElement(event, 'LI');
- if(this.index != element.autocompleteIndex)
- {
- this.index = element.autocompleteIndex;
- this.render();
- }
- Event.stop(event);
- },
-
- onClick: function(event) {
- var element = Event.findElement(event, 'LI');
- this.index = element.autocompleteIndex;
- this.select_entry();
- Event.stop(event);
- },
-
- onBlur: function(event) {
- // needed to make click events working
- setTimeout(this.hide.bind(this), 250);
- this.has_focus = false;
- this.active = false;
- },
-
- render: function() {
- if(this.entry_count > 0) {
- for (var i = 0; i < this.entry_count; i++)
- this.index==i ?
- Element.addClassName(this.get_entry(i),"selected") :
- Element.removeClassName(this.get_entry(i),"selected");
-
- if(this.has_focus) {
- if(this.get_current_entry().scrollIntoView)
- this.get_current_entry().scrollIntoView(false);
-
- this.show();
- this.active = true;
- }
- } else this.hide();
- },
-
- mark_previous: function() {
- if(this.index > 0) this.index--
- else this.index = this.entry_count-1;
- },
-
- mark_next: function() {
- if(this.index < this.entry_count-1) this.index++
- else this.index = 0;
- },
-
- get_entry: function(index) {
- return this.update.firstChild.childNodes[index];
- },
-
- get_current_entry: function() {
- return this.get_entry(this.index);
- },
-
- select_entry: function() {
- this.active = false;
- value = Element.collectTextNodesIgnoreClass(this.get_current_entry(), 'informal').unescapeHTML();
- this.updateElement(value);
- this.element.focus();
- },
-
- updateElement: function(value) {
- var last_token_pos = this.findLastToken();
- if (last_token_pos != -1) {
- var new_value = this.element.value.substr(0, last_token_pos + 1);
- var whitespace = this.element.value.substr(last_token_pos + 1).match(/^\s+/);
- if (whitespace)
- new_value += whitespace[0];
- this.element.value = new_value + value;
- } else {
- this.element.value = value;
- }
- },
-
- updateChoices: function(choices) {
- if(!this.changed && this.has_focus) {
- this.update.innerHTML = choices;
- Element.cleanWhitespace(this.update);
- Element.cleanWhitespace(this.update.firstChild);
-
- if(this.update.firstChild && this.update.firstChild.childNodes) {
- this.entry_count =
- this.update.firstChild.childNodes.length;
- for (var i = 0; i < this.entry_count; i++) {
- entry = this.get_entry(i);
- entry.autocompleteIndex = i;
- this.addObservers(entry);
- }
- } else {
- this.entry_count = 0;
- }
-
- this.stopIndicator();
-
- this.index = 0;
- this.render();
- }
- },
-
- addObservers: function(element) {
- Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
- Event.observe(element, "click", this.onClick.bindAsEventListener(this));
- },
-
- onObserverEvent: function() {
- this.changed = false;
- if(this.getEntry().length>=this.options.min_chars) {
- this.startIndicator();
- this.getUpdatedChoices();
- } else {
- this.active = false;
- this.hide();
- }
- },
-
- getEntry: function() {
- var token_pos = this.findLastToken();
- if (token_pos != -1)
- var ret = this.element.value.substr(token_pos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
- else
- var ret = this.element.value;
-
- return /\n/.test(ret) ? '' : ret;
- },
-
- findLastToken: function() {
- var last_token_pos = -1;
-
- for (var i=0; i last_token_pos)
- last_token_pos = this_token_pos;
- }
- return last_token_pos;
- }
-}
-
-Ajax.Autocompleter = Class.create();
-Ajax.Autocompleter.prototype = Object.extend(new Autocompleter.Base(),
-Object.extend(new Ajax.Base(), {
- initialize: function(element, update, url, options) {
- this.base_initialize(element, update, options);
- this.options.asynchronous = true;
- this.options.onComplete = this.onComplete.bind(this)
- this.options.method = 'post';
- this.options.defaultParams = this.options.parameters || null;
- this.url = url;
- },
-
- getUpdatedChoices: function() {
- entry = encodeURIComponent(this.element.name) + '=' +
- encodeURIComponent(this.getEntry());
-
- this.options.parameters = this.options.callback ?
- this.options.callback(this.element, entry) : entry;
-
- if(this.options.defaultParams)
- this.options.parameters += '&' + this.options.defaultParams;
-
- new Ajax.Request(this.url, this.options);
- },
-
- onComplete: function(request) {
- this.updateChoices(request.responseText);
- }
-
-}));
-
-// The local array autocompleter. Used when you'd prefer to
-// inject an array of autocompletion options into the page, rather
-// than sending out Ajax queries, which can be quite slow sometimes.
-//
-// The constructor takes four parameters. The first two are, as usual,
-// the id of the monitored textbox, and id of the autocompletion menu.
-// The third is the array you want to autocomplete from, and the fourth
-// is the options block.
-//
-// Extra local autocompletion options:
-// - choices - How many autocompletion choices to offer
-//
-// - partial_search - If false, the autocompleter will match entered
-// text only at the beginning of strings in the
-// autocomplete array. Defaults to true, which will
-// match text at the beginning of any *word* in the
-// strings in the autocomplete array. If you want to
-// search anywhere in the string, additionally set
-// the option full_search to true (default: off).
-//
-// - full_search - Search anywhere in autocomplete array strings.
-//
-// - partial_chars - How many characters to enter before triggering
-// a partial match (unlike min_chars, which defines
-// how many characters are required to do any match
-// at all). Defaults to 2.
-//
-// - ignore_case - Whether to ignore case when autocompleting.
-// Defaults to true.
-//
-// It's possible to pass in a custom function as the 'selector'
-// option, if you prefer to write your own autocompletion logic.
-// In that case, the other options above will not apply unless
-// you support them.
-
-Autocompleter.Local = Class.create();
-Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
- initialize: function(element, update, array, options) {
- this.base_initialize(element, update, options);
- this.options.array = array;
- },
-
- getUpdatedChoices: function() {
- this.updateChoices(this.options.selector(this));
- },
-
- setOptions: function(options) {
- this.options = Object.extend({
- choices: 10,
- partial_search: true,
- partial_chars: 2,
- ignore_case: true,
- full_search: false,
- selector: function(instance) {
- var ret = new Array(); // Beginning matches
- var partial = new Array(); // Inside matches
- var entry = instance.getEntry();
- var count = 0;
-
- for (var i = 0; i < instance.options.array.length &&
- ret.length < instance.options.choices ; i++) {
- var elem = instance.options.array[i];
- var found_pos = instance.options.ignore_case ?
- elem.toLowerCase().indexOf(entry.toLowerCase()) :
- elem.indexOf(entry);
-
- while (found_pos != -1) {
- if (found_pos == 0 && elem.length != entry.length) {
- ret.push("
<%= end_form_tag %>
diff --git a/test/functional/file_controller_test.rb b/test/functional/file_controller_test.rb
index 24fc2125..80b9099e 100755
--- a/test/functional/file_controller_test.rb
+++ b/test/functional/file_controller_test.rb
@@ -121,12 +121,12 @@ class FileControllerTest < Test::Unit::TestCase
def test_uploads_blocking
set_web_property :allow_uploads, true
- r = process 'file', 'web' => 'wiki1', 'id' => 'filename'
+ process 'file', 'web' => 'wiki1', 'id' => 'filename'
assert_success
set_web_property :allow_uploads, false
- r = process 'file', 'web' => 'wiki1', 'id' => 'filename'
- assert_equal '403 Forbidden', r.headers['Status']
+ process 'file', 'web' => 'wiki1', 'id' => 'filename'
+ assert_response 403
end
end
From 0c412e4a26c854ab66493c4c4dfdfc0b57e069bb Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Fri, 4 Nov 2005 05:26:32 +0000
Subject: [PATCH 82/84] CHANGELOG update. Previous commit also included:
reenabled FileController, refactoring of authorization code and some other
tweaks
---
CHANGELOG | 2 ++
1 file changed, 2 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index 6b2dcbda..d8e49998 100755
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,8 @@
SQL-based backend (ActiveRecord)
Replaced internal link generator with routing
Fixed --daemon option
+ Upgraded to Rails 0.14.2
+ Re-enabled file uploads
* 0.10.2:
Upgraded to Rails 0.13.1
From 4779a4fa4eefc6aec061f93dfd032844a3a1f6e8 Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Fri, 4 Nov 2005 05:57:31 +0000
Subject: [PATCH 83/84] Diocumented installation and data migration in README
---
README | 53 ++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 40 insertions(+), 13 deletions(-)
diff --git a/README b/README
index 09d29a9f..ae268ea1 100755
--- a/README
+++ b/README
@@ -4,10 +4,20 @@ Admitted, it's YetAnotherWikiClone[http://c2.com/cgi/wiki?WikiWikiClones], but w
on simplicity of installation and running:
Step 1. Download
-
Step 2. Run "instiki"
-Step 3. Chuckle... "There's no step three!" (TM)
+Here it should say: "Step 3. Chuckle... "There's no step three!" (TM)"
+... but this is a beta version that introduces an SQL-based backend, so:
+
+3. Kill 'instiki'
+4. Install SQLite 3 database engine from http://www.sqlite.org/
+5. Install SQLite 3 driver for Ruby from http://sqlite-ruby.rubyforge.org/
+6. Install Rake from http://rake.rubyforge.org/
+7. Execute 'rake db_schema_import create_sessions_table'
+8. Make an embarrassed sigh (as I do while writing this)
+9. Run 'instiki' again
+10. Pat yourself on the shoulder for being such a talented geek
+11. At least, there is no step eleven! (TM)
You're now running a perfectly suitable wiki on port 2500
that'll present you with one-step setup, followed by a textarea for the home page
@@ -38,21 +48,35 @@ gathering.
===Missing:
* File attachments
-===Install from gem:
-* Install rubygems
-* Run "gem install instiki"
-* Change to a directory where you want Instiki to keep its data files (for example, ~/instiki/)
-* Run "instiki" - this will create a "storage" directory (for example, ~/instiki/storage), and start a new Wiki service
-
-Make sure that you always launch Instiki from the same working directory, or specify the storage directory in runtime parameters, such as:
- instiki --storage ~/instiki/storage
-
===Command-line options:
* Run "instiki --help"
===History:
* See CHANGELOG
+===Migrating Instiki 0.10.2 storage to Instiki-AR database
+1. Install Instiki-AR and check that it works (you should be able to create a web, edit and save a HomePage)
+2. Execute
+ ruby script\import_storage \
+ -t /full/path/to/instiki0.10/storage \
+ -i /full/path/to/instiki0.10/installation \
+ -d sqlite (or mysql, or postgres, depending on what you use) \
+ -o instiki_import.sql
+ for example:
+ ruby script\import_storage -t c:\instiki-0.10.2\storage\2500 -i c:\instiki-0.10.2 -d sqlite -o instiki_import.sql
+3. This will produce instiki_import.sql file in the current working directory.
+ Open it in a text editor and inspect carefully.
+4. Connect to your production database (e.g., 'sqlite3 db\prod.db'),
+ and have it execute instiki_import.sql (e.g., '.read instiki_import.sql')
+5. Execute ruby script\reset_references
+ (this script parses all pages for crosslinks between them, so it may take a few minutes)
+6. Restart Instiki
+7. Go over some pages, especially those with a lot of complex markup, and see if anything is broken.
+
+The most common migration problem is this:
+If you open All Pages screen and see a lot of orphaned pages,
+you forgot to run ruby script\reset_references after importing the data.
+
===Download latest from:
* http://rubyforge.org/project/showfiles.php?group_id=186
@@ -63,8 +87,11 @@ Make sure that you always launch Instiki from the same working directory, or spe
* same as Ruby's
---
-Author:: David Heinemeier Hansson
+Authors::
+
+Versions 0.1 to 0.9.1:: David Heinemeier Hansson
Email:: david@loudthinking.com
Weblog:: http://www.loudthinking.com
-
+From 0.9.2 onwards:: Alexey Verkhovsky
+Email:: alex@verk.info
From c7295287a4f72dab610398684a186c0407961a1d Mon Sep 17 00:00:00 2001
From: Alexey Verkhovsky
Date: Fri, 4 Nov 2005 06:19:10 +0000
Subject: [PATCH 84/84] Extract the inbound links list from page.rhtml and
revision.rhtml into a partial
---
app/views/wiki/_inbound_links.rhtml | 13 +++++++++++++
app/views/wiki/page.rhtml | 23 +++--------------------
app/views/wiki/revision.rhtml | 13 ++-----------
3 files changed, 18 insertions(+), 31 deletions(-)
create mode 100644 app/views/wiki/_inbound_links.rhtml
diff --git a/app/views/wiki/_inbound_links.rhtml b/app/views/wiki/_inbound_links.rhtml
new file mode 100644
index 00000000..4c5e4e12
--- /dev/null
+++ b/app/views/wiki/_inbound_links.rhtml
@@ -0,0 +1,13 @@
+<% unless @page.linked_from.empty? %>
+
+ | Linked from:
+ <%= @page.linked_from.collect { |referring_page| link_to_existing_page referring_page }.join(", ") %>
+
+<% end %>
+
+<% unless @page.included_from.empty? %>
+
+ | Included from:
+ <%= @page.included_from.collect { |referring_page| link_to_existing_page referring_page }.join(", ") %>
+
+<% end %>
diff --git a/app/views/wiki/page.rhtml b/app/views/wiki/page.rhtml
index 432f688b..b7292e35 100644
--- a/app/views/wiki/page.rhtml
+++ b/app/views/wiki/page.rhtml
@@ -71,8 +71,8 @@
| Views:
<%= link_to('Print',
- {:web => @web.address, :action => 'print', :id => @page.name},
- {:accesskey => 'p', :name => 'view_print'}) %>
+ { :web => @web.address, :action => 'print', :id => @page.name },
+ { :accesskey => 'p', :name => 'view_print' }) %>
<% if defined? RedClothForTex and RedClothForTex.available? and @web.markup == :textile %>
|
<%= link_to 'TeX', {:web => @web.address, :action => 'tex', :id => @page.name},
@@ -83,24 +83,7 @@
<% end %>
- <% unless @page.linked_from.empty? %>
-
- | Linked from:
- <%= @page.linked_from.collect { |referring_page|
- link_to_existing_page referring_page
- }.join(", ")
- %>
-
- <% end %>
-
- <% if @page.included_from.length > 0 %>
-
- | Included from: <%= @page.included_from.collect { |referring_page|
- link_to_existing_page referring_page
- }.join(", ")
- %>
-
- <% end %>
+ <%= render :partial => 'inbound_links' %>