Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Knox <dknox@threedotloft.com>2013-03-11 06:10:44 +0400
committerDan Knox <dknox@threedotloft.com>2013-03-11 06:10:44 +0400
commitf0aa54e0fbce27600aa02a1ee5465e2ab5c18ccc (patch)
treec659653b69885d87745fb7e55a5f3c8d1b8d42db
parent1479f1722702c955ed3ee9456107c6a1a7277c7b (diff)
Create Wiki migration task.
This commit adds a new Rake task for migrating all of your existing Wiki content from your database into new Gollum repositories. The bulk of the logic happens within the `WikiToGollumMigrator` class which is decently test covered and located in the lib directory. The new Rake task can be executed by running: `bundle exec rake gitlab:wiki:migrate` It will output a nice log of every project that it migrates along with success or failure messages. I have used it on my own installation to migrate my Wikis successfully.
-rw-r--r--lib/tasks/gitlab/migrate_wiki.rake20
-rw-r--r--lib/wiki_to_gollum_migrator.rb103
-rw-r--r--spec/lib/wiki_to_gollum_migrator_spec.rb114
3 files changed, 237 insertions, 0 deletions
diff --git a/lib/tasks/gitlab/migrate_wiki.rake b/lib/tasks/gitlab/migrate_wiki.rake
new file mode 100644
index 00000000000..9b2f34c6b19
--- /dev/null
+++ b/lib/tasks/gitlab/migrate_wiki.rake
@@ -0,0 +1,20 @@
+namespace :gitlab do
+ namespace :wiki do
+
+ # This task will migrate all of the existing Wiki
+ # content stored in your database into the new
+ # Gollum Wiki system. A new repository named
+ # namespace/project.wiki.git will be created for
+ # each project that currently has Wiki pages in
+ # the database.
+ #
+ # Notes:
+ # * The existing Wiki content will remain in your
+ # database in-tact.
+ desc "GITLAB | Migrate Wiki content from database to Gollum repositories."
+ task :migrate => :environment do
+ wiki_migrator = WikiToGollumMigrator.new
+ wiki_migrator.migrate!
+ end
+ end
+end
diff --git a/lib/wiki_to_gollum_migrator.rb b/lib/wiki_to_gollum_migrator.rb
new file mode 100644
index 00000000000..6083533b7e2
--- /dev/null
+++ b/lib/wiki_to_gollum_migrator.rb
@@ -0,0 +1,103 @@
+class WikiToGollumMigrator
+
+ attr_reader :projects
+
+ def initialize
+ @projects = []
+
+ Project.find_in_batches(batch_size: 50) do |batch|
+ batch.each { |p| @projects << p if p.wikis.any? }
+ end
+ end
+
+ def migrate!
+ projects.each do |project|
+ log "\nMigrating Wiki for '#{project.path_with_namespace}'"
+ wiki = create_gollum_repo(project)
+ create_pages project, wiki
+ log "Project '#{project.path_with_namespace}' migrated. " + "[OK]".green
+ end
+ end
+
+ private
+
+ def create_gollum_repo(project)
+ GollumWiki.new(project, nil).wiki
+ end
+
+ def create_pages(project, wiki)
+ pages = project.wikis.group(:slug).all
+
+ pages.each do |page|
+ create_page_and_revisions(project, page)
+ end
+ end
+
+ def create_page_and_revisions(project, page)
+ # Grab all revisions of the page
+ revisions = project.wikis.where(slug: page.slug).ordered.all
+
+ # Remove the first revision created from the array
+ # and use it to create the Gollum page. Each successive revision
+ # will then be applied to the new Gollum page as an update.
+ first_rev = revisions.pop
+
+ wiki = GollumWiki.new(project, page.user)
+ wiki_page = WikiPage.new(wiki)
+
+ attributes = extract_attributes_from_page(first_rev)
+
+ if wiki_page.create(attributes)
+ log " Created page '#{wiki_page.title}' " + "[OK]".green
+
+ # Reverse the revisions to create them in the correct
+ # chronological order.
+ create_revisions(project, wiki_page, revisions.reverse)
+ else
+ log " Failed to create page '#{wiki_page.title}' " + "[FAILED]".red
+ end
+ end
+
+ def create_revisions(project, page, revisions)
+ revisions.each do |revision|
+ log " Creating revisions..."
+ # Reinitialize a new GollumWiki instance for each page
+ # and revision created so the correct User is shown in
+ # the commit message.
+ wiki = GollumWiki.new(project, revision.user)
+ wiki_page = wiki.find_page(page.slug)
+
+ attributes = extract_attributes_from_page(revision)
+
+ content = attributes[:content]
+
+ if wiki_page.update(content)
+ log " Created revision " + "[OK]".green
+ else
+ log " Failed to create revision " + "[FAILED]".red
+ end
+ end
+ end
+
+ def extract_attributes_from_page(page)
+ attributes = page.attributes
+ .with_indifferent_access
+ .slice(:title, :content)
+
+ # Change 'index' pages to 'home' pages to match Gollum standards
+ if attributes[:title].downcase == "index"
+ attributes[:title] = "home" unless home_already_exists?(project)
+ end
+
+ attributes
+ end
+
+ def home_already_exists?(project)
+ project.wikis.where(title: 'home').any? || project.wikis.where(title: 'Home').any?
+ end
+
+ def log(message)
+ puts message
+ end
+
+end
diff --git a/spec/lib/wiki_to_gollum_migrator_spec.rb b/spec/lib/wiki_to_gollum_migrator_spec.rb
new file mode 100644
index 00000000000..a784d836d62
--- /dev/null
+++ b/spec/lib/wiki_to_gollum_migrator_spec.rb
@@ -0,0 +1,114 @@
+require "spec_helper"
+
+describe WikiToGollumMigrator do
+
+ def create_wiki_for(project)
+ 3.times { @pages[project.id] << create_page(project) }
+ end
+
+ def create_revisions_for(project)
+ @pages[project.id].each do |page|
+ create_revision(page)
+ end
+ end
+
+ def create_page(project)
+ page = project.wikis.new(title: "Page #{rand(1000)}", content: "Content")
+ page.user = project.owner
+ page.slug = page.title.parameterize
+ page.save!
+ page
+ end
+
+ def create_revision(page)
+ revision = page.dup
+ revision.content = "Updated Content"
+ revision.save!
+ end
+
+ def create_temp_repo(path)
+ FileUtils.mkdir_p path
+ command = "git init --quiet --bare #{path};"
+ system(command)
+ end
+
+ before do
+ @repo_path = "#{Rails.root}/tmp/test-git-base-path"
+ @projects = []
+ @pages = Hash.new {|h,k| h[k] = Array.new }
+
+ @projects << create(:project)
+ @projects << create(:project)
+
+ @projects.each do |project|
+ create_wiki_for project
+ create_revisions_for project
+ end
+
+ @project_without_wiki = create(:project)
+ end
+
+ context "Before the migration" do
+ it "has two projects with valid wikis" do
+ @projects.each do |project|
+ pages = project.wikis.group(:slug).all
+ pages.count.should == 3
+ end
+ end
+
+ it "has two revision for each page" do
+ @projects.each do |project|
+ @pages[project.id].each do |page|
+ revisions = project.wikis.where(slug: page.slug)
+ revisions.count.should == 2
+ end
+ end
+ end
+ end
+
+ describe "#initialize" do
+ it "finds all projects that have existing wiki pages" do
+ Project.count.should == 3
+ subject.projects.count.should == 2
+ end
+ end
+
+ context "#migrate!" do
+ before do
+ Gitlab::Shell.any_instance.stub(:add_repository) do |path|
+ create_temp_repo("#{@repo_path}/#{path}.git")
+ end
+
+ subject.stub(:log).as_null_object
+
+ subject.migrate!
+ end
+
+ it "creates a new Gollum Wiki for each project" do
+ @projects.each do |project|
+ wiki_path = project.path_with_namespace + ".wiki.git"
+ full_path = @repo_path + "/" + wiki_path
+ File.exist?(full_path).should be_true
+ File.directory?(full_path).should be_true
+ end
+ end
+
+ it "creates a gollum page for each unique Wiki page" do
+ @projects.each do |project|
+ wiki = GollumWiki.new(project, nil)
+ wiki.pages.count.should == 3
+ end
+ end
+
+ it "creates a new revision for each old revision of the page" do
+ @projects.each do |project|
+ wiki = GollumWiki.new(project, nil)
+ wiki.pages.each do |page|
+ page.versions.count.should == 2
+ end
+ end
+ end
+ end
+
+
+end