caramelize 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +55 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +47 -0
- data/LICENSE.md +7 -0
- data/README.md +62 -0
- data/Rakefile +2 -0
- data/bin/caramelize +12 -0
- data/caramel.rb +62 -0
- data/caramelize.gemspec +28 -0
- data/lib/caramelize/author.rb +8 -0
- data/lib/caramelize/cli/create_command.rb +47 -0
- data/lib/caramelize/cli/run_command.rb +22 -0
- data/lib/caramelize/cli.rb +95 -0
- data/lib/caramelize/content_transferer.rb +64 -0
- data/lib/caramelize/database_connector.rb +20 -0
- data/lib/caramelize/ext.rb +17 -0
- data/lib/caramelize/gollum_output.rb +71 -0
- data/lib/caramelize/page.rb +30 -0
- data/lib/caramelize/redmine_wiki.rb +66 -0
- data/lib/caramelize/version.rb +3 -0
- data/lib/caramelize/wiki.rb +42 -0
- data/lib/caramelize/wikka2markdown_converter.rb +28 -0
- data/lib/caramelize/wikkawiki.rb +50 -0
- data/test/helper.rb +18 -0
- data/test/test_caramelize.rb +7 -0
- metadata +108 -0
data/.gitignore
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
wiki.git
|
2
|
+
|
3
|
+
# rcov generated
|
4
|
+
coverage
|
5
|
+
|
6
|
+
# rdoc generated
|
7
|
+
rdoc
|
8
|
+
|
9
|
+
# yard generated
|
10
|
+
doc
|
11
|
+
.yardoc
|
12
|
+
|
13
|
+
# bundler
|
14
|
+
.bundle
|
15
|
+
Gemfile.lock
|
16
|
+
*.gem
|
17
|
+
|
18
|
+
# jeweler generated
|
19
|
+
pkg/*
|
20
|
+
|
21
|
+
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
22
|
+
#
|
23
|
+
# * Create a file at ~/.gitignore
|
24
|
+
# * Include files you want ignored
|
25
|
+
# * Run: git config --global core.excludesfile ~/.gitignore
|
26
|
+
#
|
27
|
+
# After doing this, these files will be ignored in all your git projects,
|
28
|
+
# saving you from having to 'pollute' every project you touch with them
|
29
|
+
#
|
30
|
+
# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
|
31
|
+
#
|
32
|
+
# For MacOS:
|
33
|
+
#
|
34
|
+
.DS_Store
|
35
|
+
|
36
|
+
# For TextMate
|
37
|
+
#*.tmproj
|
38
|
+
#tmtags
|
39
|
+
|
40
|
+
# For Komodo Edit
|
41
|
+
#*.komodoproject
|
42
|
+
|
43
|
+
# For emacs:
|
44
|
+
#*~
|
45
|
+
#\#*
|
46
|
+
#.\#*
|
47
|
+
|
48
|
+
# For vim:
|
49
|
+
#*.swp
|
50
|
+
|
51
|
+
# For redcar:
|
52
|
+
#.redcar
|
53
|
+
|
54
|
+
# For rubinius:
|
55
|
+
#*.rbc
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
caramelize (0.0.1)
|
5
|
+
gollum (>= 1.3.0)
|
6
|
+
mysql2
|
7
|
+
treetop (>= 1.4.9)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
albino (1.3.3)
|
13
|
+
posix-spawn (>= 0.3.6)
|
14
|
+
diff-lcs (1.1.2)
|
15
|
+
github-markup (0.5.3)
|
16
|
+
gollum (1.3.0)
|
17
|
+
albino (~> 1.3.2)
|
18
|
+
github-markup (>= 0.4.0, < 1.0.0)
|
19
|
+
grit (~> 2.4.1)
|
20
|
+
mustache (>= 0.11.2, < 1.0.0)
|
21
|
+
nokogiri (~> 1.4)
|
22
|
+
sanitize (~> 2.0.0)
|
23
|
+
sinatra (~> 1.0)
|
24
|
+
grit (2.4.1)
|
25
|
+
diff-lcs (~> 1.1)
|
26
|
+
mime-types (~> 1.15)
|
27
|
+
mime-types (1.16)
|
28
|
+
mustache (0.99.4)
|
29
|
+
mysql2 (0.3.2)
|
30
|
+
nokogiri (1.4.4)
|
31
|
+
polyglot (0.3.1)
|
32
|
+
posix-spawn (0.3.6)
|
33
|
+
rack (1.3.0)
|
34
|
+
sanitize (2.0.2)
|
35
|
+
nokogiri (~> 1.4.4)
|
36
|
+
sinatra (1.2.6)
|
37
|
+
rack (~> 1.1)
|
38
|
+
tilt (>= 1.2.2, < 2.0)
|
39
|
+
tilt (1.3.2)
|
40
|
+
treetop (1.4.9)
|
41
|
+
polyglot (>= 0.3.1)
|
42
|
+
|
43
|
+
PLATFORMS
|
44
|
+
ruby
|
45
|
+
|
46
|
+
DEPENDENCIES
|
47
|
+
caramelize!
|
data/LICENSE.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2011 Daniel Senff
|
2
|
+
|
3
|
+
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:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
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.
|
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# caramelize
|
2
|
+
|
3
|
+
Caramelize is a compact and flexible wiki converter. It is intended for easily creating export of otherwise rare supported legacy wikis. With caramelize you can create your own export configurations and transfer your data into a git-based gollum-wiki retaing all your history.
|
4
|
+
|
5
|
+
In the future more target wiki system may be added. For the moment export is supported for WikkaWiki and Redmine-Wiki.
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
### Building
|
10
|
+
|
11
|
+
For the moment caramelize is not yet stable and not released to any gemsites.
|
12
|
+
|
13
|
+
To try it you require bundler to build it.
|
14
|
+
|
15
|
+
$ gem bundler install
|
16
|
+
|
17
|
+
Clone this repository and start building.
|
18
|
+
|
19
|
+
$ git clone git@github.com:Dahie/caramelize.git
|
20
|
+
$ gem build caramelize.gemspec
|
21
|
+
|
22
|
+
Now to build the gem do
|
23
|
+
|
24
|
+
$ rake build
|
25
|
+
|
26
|
+
or
|
27
|
+
|
28
|
+
$ rake install
|
29
|
+
|
30
|
+
to install the new gem right to the system.
|
31
|
+
|
32
|
+
### Use
|
33
|
+
|
34
|
+
$ caramelize create --config=config.rb
|
35
|
+
|
36
|
+
Creates a template configuration file. This includes documentation on how to use the preset Wiki-connectors and how to write addition customized connectors.
|
37
|
+
|
38
|
+
|
39
|
+
$ caramelize run
|
40
|
+
|
41
|
+
Will execute a wiki migration based on a found configuration file. These are found in predefined paths.
|
42
|
+
|
43
|
+
$ caramelize help
|
44
|
+
Returns help information.
|
45
|
+
|
46
|
+
$ caramelize version
|
47
|
+
Returns version and release information.
|
48
|
+
|
49
|
+
## Contributing to caramelize
|
50
|
+
|
51
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
52
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
53
|
+
* Fork the project
|
54
|
+
* Start a feature/bugfix branch
|
55
|
+
* Commit and push until you are happy with your contribution
|
56
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
57
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
58
|
+
|
59
|
+
## Copyright
|
60
|
+
|
61
|
+
Copyright (c) 2011 Daniel Senff. See LICENSE.md for further details.
|
62
|
+
|
data/Rakefile
ADDED
data/bin/caramelize
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# If we are given filenames, convert each file
|
4
|
+
|
5
|
+
require 'caramelize/cli'
|
6
|
+
begin
|
7
|
+
Caramelize::CLI::CommandParser.new.parse
|
8
|
+
rescue
|
9
|
+
puts "An error has occurred:\n " + $!.message
|
10
|
+
puts $!.backtrace if $DEBUG
|
11
|
+
exit(-1)
|
12
|
+
end
|
data/caramel.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'caramelize/wiki'
|
2
|
+
require 'caramelize/wikkawiki'
|
3
|
+
require 'caramelize/redmine_wiki'
|
4
|
+
|
5
|
+
# Within this method you can define your own Wiki-Connectors to Wikis not supported by default in this software
|
6
|
+
|
7
|
+
# Note, if you want to activate this, you need to uncomment the line below.
|
8
|
+
def customized_wiki
|
9
|
+
|
10
|
+
# This example is a reimplementation of the WikkaWiki-Connector.
|
11
|
+
# To connect to WikkaWiki, I suggest to use the predefined Connector below.
|
12
|
+
wiki = Caramelize::Wiki.new(:host => "localhost", :username => "user", :database => "database_name", :password => 'admin_gnihihihi', :syntax => :wikka)
|
13
|
+
wiki.instance_eval do
|
14
|
+
def read_pages
|
15
|
+
sql = "SELECT id, tag, body, time, latest, user, note FROM wikka_pages ORDER BY time;"
|
16
|
+
@revisions, @titles = [], []
|
17
|
+
results = database.query(sql)
|
18
|
+
results.each do |row|
|
19
|
+
@titles << row["tag"]
|
20
|
+
author = @authors[row["user"]]
|
21
|
+
page = Page.new({:id => row["id"],
|
22
|
+
:title => row["tag"],
|
23
|
+
:body => row["body"],
|
24
|
+
:syntax => 'wikka',
|
25
|
+
:latest => row["latest"] == "Y",
|
26
|
+
:time => row["time"],
|
27
|
+
:message => row["note"],
|
28
|
+
:author => author,
|
29
|
+
:author_name => row["user"]})
|
30
|
+
@revisions << page
|
31
|
+
end
|
32
|
+
@titles.uniq!
|
33
|
+
@revisions
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
wiki
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
# if you want to use one of the preset Wiki-Connectors uncomment the connector
|
43
|
+
# and edit the database logins accordingly.
|
44
|
+
def predefined_wiki
|
45
|
+
|
46
|
+
# For connection to a WikkaWiki-Database use this Connector
|
47
|
+
#return Caramelize::WikkaWiki.new(:host => "localhost", :username => "root", :database => "wikka")
|
48
|
+
|
49
|
+
|
50
|
+
# For connection to a Redmine-Database use this Connector
|
51
|
+
return Caramelize::RedmineWiki.new(:host => "localhost", :username => "root", :database => "redmine_development")
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def input_wiki
|
56
|
+
|
57
|
+
# comment and uncomment to easily switch between predefined and costumized Wiki-connectors.
|
58
|
+
#return customized_wiki
|
59
|
+
|
60
|
+
return predefined_wiki
|
61
|
+
|
62
|
+
end
|
data/caramelize.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "caramelize/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "caramelize"
|
7
|
+
s.version = Caramelize::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.license = "MIT"
|
10
|
+
s.authors = ["Daniel Senff"]
|
11
|
+
s.email = ["mail@danielsenff.de"]
|
12
|
+
s.homepage = "http://github.com/Dahie/caramelize"
|
13
|
+
s.summary = %q{Abstract wiki convert to migrate your data from one wiki software to another}
|
14
|
+
s.description = %q{By defining the access from the input to the output wiki you can migrate any wiki.}
|
15
|
+
|
16
|
+
s.bindir = 'bin'
|
17
|
+
|
18
|
+
s.add_dependency('mysql2')
|
19
|
+
s.add_dependency('cmdparse')
|
20
|
+
s.add_dependency('gollum', '>= 1.3.0') # grit dependency implicit through gollum
|
21
|
+
|
22
|
+
s.rubyforge_project = "caramelize"
|
23
|
+
|
24
|
+
s.files = `git ls-files`.split("\n")
|
25
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
26
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
27
|
+
s.require_paths = ["lib"]
|
28
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#Encoding: UTF-8
|
2
|
+
|
3
|
+
require 'caramelize/cli'
|
4
|
+
|
5
|
+
module Caramelize::CLI
|
6
|
+
|
7
|
+
# The CLI command for creating a caramelize config file.
|
8
|
+
class CreateCommand < CmdParse::Command
|
9
|
+
|
10
|
+
def initialize #:nodoc:
|
11
|
+
super('create', false)
|
12
|
+
#self.description = Utils.format("If the verbosity level is set to verbose, the created files are listed.")
|
13
|
+
self.short_desc = 'Create a default config file for caramelize'
|
14
|
+
self.options = CmdParse::OptionParserWrapper.new do |opts|
|
15
|
+
opts.separator "Arguments:"
|
16
|
+
opts.separator opts.summary_indent + "DIR: the directory in which the website should be created"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def usage # :nodoc:
|
21
|
+
"Usage: #{commandparser.program_name} [global options] create [options] DIR"
|
22
|
+
end
|
23
|
+
|
24
|
+
# Create a caramelize config file in the directory <tt>args[0]</tt>.
|
25
|
+
def execute(args)
|
26
|
+
if args.length == 0
|
27
|
+
raise OptionParser::MissingArgument.new('DIR')
|
28
|
+
else
|
29
|
+
begin
|
30
|
+
|
31
|
+
# TODO create dummy config file
|
32
|
+
|
33
|
+
rescue
|
34
|
+
require 'fileutils'
|
35
|
+
FileUtils.rm_rf(args[0])
|
36
|
+
raise
|
37
|
+
end
|
38
|
+
if commandparser.verbosity == :verbose
|
39
|
+
puts "The following files were created in the directory #{args[0]}:"
|
40
|
+
#puts paths.sort.join("\n")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#Encoding: UTF-8
|
2
|
+
|
3
|
+
require 'caramelize/cli'
|
4
|
+
|
5
|
+
module Caramelize::CLI
|
6
|
+
|
7
|
+
# The CLI command for rendering a webgen website.
|
8
|
+
class RunCommand < CmdParse::Command
|
9
|
+
|
10
|
+
def initialize # :nodoc:
|
11
|
+
super('run', false)
|
12
|
+
self.short_desc = 'Run the wiki content transfer based on the given config file'
|
13
|
+
end
|
14
|
+
|
15
|
+
# Transfer Wiki contents
|
16
|
+
def execute(args)
|
17
|
+
commandparser.transfer_content
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'cmdparse'
|
2
|
+
require 'caramelize/version'
|
3
|
+
|
4
|
+
module Caramelize
|
5
|
+
module CLI
|
6
|
+
|
7
|
+
# Namespace for all classes that act as CLI commands.
|
8
|
+
autoload :RunCommand, 'caramelize/cli/run_command'
|
9
|
+
autoload :CreateCommand, 'caramelize/cli/create_command'
|
10
|
+
autoload :ContentTransferer, 'caramelize/content_transferer'
|
11
|
+
|
12
|
+
# This is the command parser class used for handling the webgen command line interface. After
|
13
|
+
# creating an instance, the inherited #parse method can be used for parsing the command line
|
14
|
+
# arguments and executing the requested command.
|
15
|
+
class CommandParser < CmdParse::CommandParser
|
16
|
+
|
17
|
+
# The website directory. Default: the current working directory.
|
18
|
+
attr_reader :directory
|
19
|
+
|
20
|
+
# The verbosity level. Default: <tt>:normal</tt>
|
21
|
+
attr_reader :verbosity
|
22
|
+
|
23
|
+
# Create a new CommandParser class. T
|
24
|
+
def initialize
|
25
|
+
super(true)
|
26
|
+
@directory = nil
|
27
|
+
@verbosity = :normal
|
28
|
+
|
29
|
+
self.program_name = "caramelize"
|
30
|
+
self.program_version = Caramelize::VERSION
|
31
|
+
self.options = CmdParse::OptionParserWrapper.new do |opts|
|
32
|
+
opts.separator "Global options:"
|
33
|
+
opts.on("--config DIR", "-d", String, "The config file (default: caramel.conf)") {|p| @directory = p}
|
34
|
+
opts.on("--verbose", "-v", "Print more output") { @verbosity = :verbose }
|
35
|
+
opts.on("--quiet", "-q", "No output") { @verbosity = :quiet }
|
36
|
+
end
|
37
|
+
self.add_command(CmdParse::HelpCommand.new)
|
38
|
+
self.add_command(CmdParse::VersionCommand.new)
|
39
|
+
end
|
40
|
+
|
41
|
+
KNOWN_CONFIG_LOCATIONS = ['config/caramel.rb', "config/caramel.config", "caramel.rb", "src/caramel.rb"]
|
42
|
+
|
43
|
+
# Finds the configuration file, if it exists in a known location.
|
44
|
+
def detect_configuration_file(config_path = nil)
|
45
|
+
possible_files = KNOWN_CONFIG_LOCATIONS
|
46
|
+
possible_files.detect{|f| File.exists?(f)}
|
47
|
+
end
|
48
|
+
|
49
|
+
# Utility method for sub-commands to create a default config file
|
50
|
+
def create_config
|
51
|
+
# TODO create dummy config
|
52
|
+
#if !defined?(@website)
|
53
|
+
#@config = Webgen::Website.new(@directory) do |config|
|
54
|
+
# config['logger.mask'] = @log_filter
|
55
|
+
#end
|
56
|
+
#end
|
57
|
+
#@config
|
58
|
+
end
|
59
|
+
|
60
|
+
# Utility method for sub-commands to transfer wiki contents
|
61
|
+
def transfer_content
|
62
|
+
# TODO maybe move to mixin
|
63
|
+
|
64
|
+
time_start = Time.now
|
65
|
+
|
66
|
+
# TODO outsource to config
|
67
|
+
file = detect_configuration_file
|
68
|
+
if file && File.exists?(file)
|
69
|
+
instance_eval(File.read(file), file || '<eval>')
|
70
|
+
original_wiki = input_wiki
|
71
|
+
|
72
|
+
ContentTransferer.execute original_wiki, {:verbosity => @verbosity}
|
73
|
+
|
74
|
+
time_end = Time.now
|
75
|
+
|
76
|
+
puts "Time required: #{time_end - time_start} s" if @verbosity
|
77
|
+
else
|
78
|
+
puts "No config file found."
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
# :nodoc:
|
84
|
+
def parse(argv = ARGV)
|
85
|
+
Caramelize::CLI.constants.select {|c| c =~ /.+Command$/ }.each do |c|
|
86
|
+
self.add_command(Caramelize::CLI.const_get(c).new, (c.to_s == 'RunCommand' ? false : false)) # set runcommand as default
|
87
|
+
end
|
88
|
+
super
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#Encoding: UTF-8
|
2
|
+
|
3
|
+
require 'gollum'
|
4
|
+
require 'grit'
|
5
|
+
|
6
|
+
module Caramelize
|
7
|
+
autoload :Wiki, 'caramelize/wiki'
|
8
|
+
autoload :WikkaWiki, 'caramelize/wikkawiki'
|
9
|
+
autoload :RedmineWiki, 'caramelize/redmine_wiki'
|
10
|
+
autoload :GollumOutput, 'caramelize/gollum_output'
|
11
|
+
autoload :Wikka2MarkdownConverter, 'wikka2markdown_converter'
|
12
|
+
autoload :Author, 'caramelize/author'
|
13
|
+
autoload :Page, 'caramelize/page'
|
14
|
+
|
15
|
+
# Controller for the content migration
|
16
|
+
class ContentTransferer
|
17
|
+
|
18
|
+
# Execute the content migration
|
19
|
+
def self.execute original_wiki, options={}
|
20
|
+
|
21
|
+
# read page revisions from wiki
|
22
|
+
# store page revisions
|
23
|
+
|
24
|
+
original_wiki.read_authors
|
25
|
+
@revisions = original_wiki.read_pages
|
26
|
+
|
27
|
+
# initiate new wiki
|
28
|
+
|
29
|
+
output_wiki = GollumOutput.new('wiki.git')
|
30
|
+
|
31
|
+
# commit page revisions to new wiki
|
32
|
+
|
33
|
+
output_wiki.commit_history @revisions
|
34
|
+
|
35
|
+
# if wiki needs to convert sytax, do so
|
36
|
+
if original_wiki.convert_syntax?
|
37
|
+
puts "latest revisions:"
|
38
|
+
# take each latest revision
|
39
|
+
for rev in original_wiki.latest_revisions
|
40
|
+
puts "Updated syntax: #{rev.title} #{rev.time}"
|
41
|
+
# parse markup & convert to new syntax
|
42
|
+
body_new = original_wiki.convert2markdown rev.body
|
43
|
+
unless body_new == rev.body
|
44
|
+
rev.body = body_new
|
45
|
+
rev.author_name = "Caramelize"
|
46
|
+
rev.time = Time.now
|
47
|
+
rev.author = nil
|
48
|
+
|
49
|
+
# commit as latest page revision
|
50
|
+
output_wiki.commit_revision rev
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
#lemma = wiki.revisions_by_title "dahie"
|
57
|
+
#for page in lemma
|
58
|
+
# puts page.time
|
59
|
+
#end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'mysql2'
|
2
|
+
|
3
|
+
module Caramelize
|
4
|
+
module DatabaseConnector
|
5
|
+
|
6
|
+
def database
|
7
|
+
socket = ["/tmp/mysqld.sock",
|
8
|
+
"/tmp/mysql.sock",
|
9
|
+
"/var/run/mysqld/mysqld.sock",
|
10
|
+
"/opt/local/var/run/mysql5/mysqld.sock",
|
11
|
+
"/var/lib/mysql/mysql.sock"].detect{|socket| File.exist?(socket) }
|
12
|
+
@options[:socket] = socket
|
13
|
+
@client = Mysql2::Client.new(@options) unless @client
|
14
|
+
@client
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'gollum'
|
2
|
+
|
3
|
+
module Gollum
|
4
|
+
class Committer
|
5
|
+
def commit
|
6
|
+
@options[:parents] = parents
|
7
|
+
@options[:actor] = actor
|
8
|
+
@options[:last_tree] = nil
|
9
|
+
@options[:head] = @wiki.ref
|
10
|
+
sha1 = index.commit(@options[:message], @options)
|
11
|
+
@callbacks.each do |cb|
|
12
|
+
cb.call(self, sha1)
|
13
|
+
end
|
14
|
+
sha1
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#Encoding: UTF-8
|
2
|
+
|
3
|
+
module Caramelize
|
4
|
+
class GollumOutput
|
5
|
+
|
6
|
+
# Initialize a new gollum-wiki-repository at the given path.
|
7
|
+
def initialize wiki_path
|
8
|
+
# TODO use sanitized name as wiki-repository-title
|
9
|
+
repo = Grit::Repo.init(wiki_path) unless File.exists?(wiki_path)
|
10
|
+
@gollum = Gollum::Wiki.new(wiki_path)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Commit the given page into the gollum-wiki-repository.
|
14
|
+
def commit_revision page
|
15
|
+
gollum_page = @gollum.page(page.title)
|
16
|
+
message = page.message.empty? ? "Edit in page #{page.title}" : page.message
|
17
|
+
|
18
|
+
if page.author
|
19
|
+
author = page.author
|
20
|
+
else
|
21
|
+
author = Author.new
|
22
|
+
author.name = page.author_name
|
23
|
+
author.email = "mail@example.com"
|
24
|
+
end
|
25
|
+
|
26
|
+
commit = {:message => message,
|
27
|
+
:name => author.name,
|
28
|
+
:email => author.email,
|
29
|
+
:authored_date => page.time,
|
30
|
+
:committed_date => page.time
|
31
|
+
}
|
32
|
+
if gollum_page
|
33
|
+
@gollum.update_page(gollum_page, gollum_page.name, gollum_page.format, page.body, commit)
|
34
|
+
else
|
35
|
+
# OPTIMIZE support not just markdown
|
36
|
+
@gollum.write_page(page.title, :markdown, page.body, commit)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Commit all revisions of the given history into this gollum-wiki-repository.
|
41
|
+
def commit_history revisions
|
42
|
+
revisions.each_with_index do |page, index|
|
43
|
+
puts "(#{index+1}/#{revisions.count}) #{page.time} #{page.title}"
|
44
|
+
|
45
|
+
gollum_page = @gollum.page(page.title)
|
46
|
+
message = page.message.empty? ? "Edit in page #{page.title}" : page.message
|
47
|
+
|
48
|
+
if page.author
|
49
|
+
author = page.author
|
50
|
+
else
|
51
|
+
author = Author.new
|
52
|
+
author.name = page.author_name
|
53
|
+
author.email = "mail@example.com"
|
54
|
+
end
|
55
|
+
|
56
|
+
commit = {:message => message,
|
57
|
+
:name => author.name,
|
58
|
+
:email => author.email,
|
59
|
+
:authored_date => page.time,
|
60
|
+
:committed_date => page.time
|
61
|
+
}
|
62
|
+
if gollum_page
|
63
|
+
@gollum.update_page(gollum_page, gollum_page.name, gollum_page.format, page.body, commit)
|
64
|
+
else
|
65
|
+
# OPTIMIZE support not just markdown
|
66
|
+
@gollum.write_page(page.title, :markdown, page.body, commit)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Caramelize
|
2
|
+
class Page
|
3
|
+
|
4
|
+
attr_accessor :title, :body, :id, :syntax, :latest, :time, :message, :author, :author_name
|
5
|
+
|
6
|
+
def initialize page={}
|
7
|
+
@id = page[:id]
|
8
|
+
@title = page[:title]
|
9
|
+
@body = page[:body]
|
10
|
+
@syntax = page[:syntax]
|
11
|
+
@latest = page[:latest]
|
12
|
+
@time = page[:time]
|
13
|
+
@message = page[:message]
|
14
|
+
@author = page[:author]
|
15
|
+
@author_name = page[:author_name]
|
16
|
+
end
|
17
|
+
|
18
|
+
def latest?
|
19
|
+
@latest
|
20
|
+
end
|
21
|
+
|
22
|
+
def set_latest
|
23
|
+
@latest = true
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s
|
27
|
+
@title
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
#Encoding: UTF-8
|
2
|
+
module Caramelize
|
3
|
+
autoload :DatabaseConnector, 'caramelize/database_connector'
|
4
|
+
autoload :Wikka2MarkdownConverter, 'caramelize/wikka2markdown_converter'
|
5
|
+
|
6
|
+
class RedmineWiki < Wiki
|
7
|
+
include DatabaseConnector
|
8
|
+
|
9
|
+
|
10
|
+
# after calling this action, I expect the @titles and @revisions to be filled
|
11
|
+
def read_pages
|
12
|
+
sql = "SELECT id, title FROM wiki_pages;"
|
13
|
+
@revisions = []
|
14
|
+
@titles = []
|
15
|
+
@latest_revisions = {}
|
16
|
+
results_pages = database.query(sql)
|
17
|
+
results_pages.each do |row_page|
|
18
|
+
results_contents = database.query("SELECT * FROM wiki_content_versions WHERE page_id='#{row_page["id"]}' ORDER BY updated_on;")
|
19
|
+
title = row_page["title"]
|
20
|
+
@titles << title
|
21
|
+
|
22
|
+
results_contents.each do |row_content|
|
23
|
+
author = @authors[row_content["author_id"]] ? @authors[row_content["author_id"]] : nil
|
24
|
+
page = Page.new({:id => row_content["id"],
|
25
|
+
:title => title,
|
26
|
+
:body => row_content["data"],
|
27
|
+
:syntax => 'textile',
|
28
|
+
:latest => false,
|
29
|
+
:time => row_content["updated_on"],
|
30
|
+
:message => row_content["comments"],
|
31
|
+
:author => author,
|
32
|
+
:author_name => author.name})
|
33
|
+
@revisions << page
|
34
|
+
@latest_revisions[title] = page
|
35
|
+
end
|
36
|
+
end
|
37
|
+
@titles.uniq!
|
38
|
+
@latest_revisions.each { |rev| rev[1].set_latest }
|
39
|
+
@revisions.sort! { |a,b| a.time <=> b.time }
|
40
|
+
|
41
|
+
|
42
|
+
# TODO find latest revision for each limit
|
43
|
+
|
44
|
+
@revisions
|
45
|
+
end
|
46
|
+
|
47
|
+
def convert_syntax?
|
48
|
+
# TODO
|
49
|
+
false
|
50
|
+
end
|
51
|
+
|
52
|
+
def read_authors
|
53
|
+
sql = "SELECT id, login, mail FROM users;"
|
54
|
+
@authors = {}
|
55
|
+
results = database.query(sql)
|
56
|
+
results.each do |row|
|
57
|
+
author = Author.new
|
58
|
+
author.id = row["id"]
|
59
|
+
author.name = row["login"]
|
60
|
+
author.email = row["mail"]
|
61
|
+
@authors[author.id] = author
|
62
|
+
end
|
63
|
+
@authors
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Caramelize
|
2
|
+
autoload :DatabaseConnector, 'caramelize/database_connector'
|
3
|
+
class Wiki
|
4
|
+
include DatabaseConnector
|
5
|
+
attr_accessor :revisions, :wiki_title, :titles, :description
|
6
|
+
|
7
|
+
#def initialize revisions
|
8
|
+
# @revisions = revisions
|
9
|
+
#end
|
10
|
+
|
11
|
+
def initialize options={}
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def revisions_by_title title
|
16
|
+
if @titles.index title
|
17
|
+
# new array only containing pages by this name sorted by time
|
18
|
+
# TODO this is probably bad for renamed pages if supported
|
19
|
+
return @revisions.reject { |revision| revision.title != title }.sort { |x,y| x.time <=> y.time }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# return an empty array in case this action was not overridden
|
24
|
+
def read_authors
|
25
|
+
return []
|
26
|
+
end
|
27
|
+
|
28
|
+
def convert_syntax?
|
29
|
+
# TODO
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
def latest_revisions
|
34
|
+
@latest_revisions = []
|
35
|
+
for title in @titles
|
36
|
+
# pick first revision by descending date
|
37
|
+
@latest_revisions << revisions_by_title(title).last
|
38
|
+
end
|
39
|
+
@latest_revisions
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Caramelize
|
2
|
+
module Wikka2MarkdownConverter
|
3
|
+
|
4
|
+
# take an input stream and convert all wikka syntax to markdown syntax
|
5
|
+
def convert2markdown str
|
6
|
+
str.gsub!(/(======)(.*?)(======)/ ) {|s| '# ' + $2 } #h1
|
7
|
+
str.gsub!(/(=====)(.*?)(=====)/) {|s| '## ' + $2 } #h2
|
8
|
+
str.gsub!(/(====)(.*?)(====)/) {|s| '### ' + $2 } #h3
|
9
|
+
str.gsub!(/(===)(.*?)(===)/) {|s| '#### ' + $2 } #h4
|
10
|
+
|
11
|
+
str.gsub!(/(\*\*)(.*?)(\*\*)/) {|s| '**' + $2 + '**' } #bold
|
12
|
+
str.gsub!(/(\/\/)(.*?)(\/\/)/) {|s| '_' + $2 + '_' } #italic
|
13
|
+
#str.gsub!(/(===)(.*?)(===)/) {|s| '`' + $2 + '`'} #code
|
14
|
+
str.gsub!(/(__)(.*?)(__)/) {|s| '<u>' + $2 + '</u>'} #underline
|
15
|
+
|
16
|
+
str.gsub!(/(.*?)(\n\t-)(.*?)/) {|s| $1 + '\n' + $3 } #list
|
17
|
+
|
18
|
+
#str.gsub!(/(\t-)(.*?)/) {|s| '*' + $2 } #list
|
19
|
+
#str.gsub!(/(----)/) {|s| '~~~~'} #seperator
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
# TODO more syntax conversion for links and images
|
24
|
+
|
25
|
+
str
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#Encoding: UTF-8
|
2
|
+
module Caramelize
|
3
|
+
autoload :DatabaseConnector, 'caramelize/database_connector'
|
4
|
+
autoload :Wikka2MarkdownConverter, 'caramelize/wikka2markdown_converter'
|
5
|
+
|
6
|
+
class WikkaWiki < Wiki
|
7
|
+
include DatabaseConnector
|
8
|
+
include Wikka2MarkdownConverter
|
9
|
+
|
10
|
+
# after calling this action, I expect the @titles and @revisions to be filled
|
11
|
+
def read_pages
|
12
|
+
sql = "SELECT id, tag, body, time, latest, user, note FROM wikka_pages ORDER BY time;"
|
13
|
+
@revisions = []
|
14
|
+
@titles = []
|
15
|
+
results = database.query(sql)
|
16
|
+
results.each do |row|
|
17
|
+
@titles << row["tag"]
|
18
|
+
author = @authors[row["user"]]
|
19
|
+
page = Page.new({:id => row["id"],
|
20
|
+
:title => row["tag"],
|
21
|
+
:body => row["body"],
|
22
|
+
:syntax => 'wikka',
|
23
|
+
:latest => row["latest"] == "Y",
|
24
|
+
:time => row["time"],
|
25
|
+
:message => row["note"],
|
26
|
+
:author => author,
|
27
|
+
:author_name => row["user"]})
|
28
|
+
@revisions << page
|
29
|
+
end
|
30
|
+
@titles.uniq!
|
31
|
+
#@revisions.sort! { |a,b| a.time <=> b.time }
|
32
|
+
|
33
|
+
@revisions
|
34
|
+
end
|
35
|
+
|
36
|
+
def read_authors
|
37
|
+
sql = "SELECT name, email FROM wikka_users;"
|
38
|
+
@authors = {}
|
39
|
+
results = database.query(sql)
|
40
|
+
results.each do |row|
|
41
|
+
author = Author.new
|
42
|
+
#author.id = row["id"]
|
43
|
+
author.name = row["name"]
|
44
|
+
author.email = row["email"]
|
45
|
+
@authors[author.name] = author
|
46
|
+
end
|
47
|
+
@authors
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
require 'shoulda'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
+
require 'caramelize'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: caramelize
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Daniel Senff
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-09-15 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: mysql2
|
16
|
+
requirement: &2156137340 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2156137340
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: cmdparse
|
27
|
+
requirement: &2156133960 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2156133960
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: gollum
|
38
|
+
requirement: &2156131900 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.3.0
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2156131900
|
47
|
+
description: By defining the access from the input to the output wiki you can migrate
|
48
|
+
any wiki.
|
49
|
+
email:
|
50
|
+
- mail@danielsenff.de
|
51
|
+
executables:
|
52
|
+
- caramelize
|
53
|
+
extensions: []
|
54
|
+
extra_rdoc_files: []
|
55
|
+
files:
|
56
|
+
- .gitignore
|
57
|
+
- Gemfile
|
58
|
+
- Gemfile.lock
|
59
|
+
- LICENSE.md
|
60
|
+
- README.md
|
61
|
+
- Rakefile
|
62
|
+
- bin/caramelize
|
63
|
+
- caramel.rb
|
64
|
+
- caramelize.gemspec
|
65
|
+
- lib/caramelize/author.rb
|
66
|
+
- lib/caramelize/cli.rb
|
67
|
+
- lib/caramelize/cli/create_command.rb
|
68
|
+
- lib/caramelize/cli/run_command.rb
|
69
|
+
- lib/caramelize/content_transferer.rb
|
70
|
+
- lib/caramelize/database_connector.rb
|
71
|
+
- lib/caramelize/ext.rb
|
72
|
+
- lib/caramelize/gollum_output.rb
|
73
|
+
- lib/caramelize/page.rb
|
74
|
+
- lib/caramelize/redmine_wiki.rb
|
75
|
+
- lib/caramelize/version.rb
|
76
|
+
- lib/caramelize/wiki.rb
|
77
|
+
- lib/caramelize/wikka2markdown_converter.rb
|
78
|
+
- lib/caramelize/wikkawiki.rb
|
79
|
+
- test/helper.rb
|
80
|
+
- test/test_caramelize.rb
|
81
|
+
homepage: http://github.com/Dahie/caramelize
|
82
|
+
licenses:
|
83
|
+
- MIT
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ! '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubyforge_project: caramelize
|
102
|
+
rubygems_version: 1.8.10
|
103
|
+
signing_key:
|
104
|
+
specification_version: 3
|
105
|
+
summary: Abstract wiki convert to migrate your data from one wiki software to another
|
106
|
+
test_files:
|
107
|
+
- test/helper.rb
|
108
|
+
- test/test_caramelize.rb
|