0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RedmineのAプロジェクトにあるWikiをBプロジェクトにコピーする

Last updated at Posted at 2021-04-01

表題のママ。
開発用のWikiで集積してたデータを運用用のプロジェクト内に移動したいみたいな話。
redmineのDBを直接読み書きできる人向け。
雑に作ってるので流す前にバックアップ必須。

Copy Wiki to another project - Redmine でアップロードされているSQLでだいたい解決するものの、

  • Wikiページに添付されたファイルが複製されない
  • パラメータがwiki_idになっているのがちょっと微妙

というのがあって修正した。

redmineのdatabase

だいたいこんな構造になってる。

plantumlソース
@startuml
class attachments{
  int id
  int content_id
  int content_type
}
class projects{
int id
}

class wikis{
int id
int project_id
}
class wiki_contents
class wiki_content_versions{
int wiki_content_id
}

class wiki_pages{
int id
int wiki_id
}

class wiki_redirects

projects -left- wikis : projects.id=wikis.project_id
wikis *-- wiki_pages
wikis *-left- wiki_redirects
wiki_pages --- wiki_contents : id
wiki_contents *-right- wiki_content_versions
wiki_pages *-right- attachments : attachments.container_type='WikiPage'\nattachments.container_id=wiki_pages.id
@enduml

まずはプロジェクトidを調べる

redmineのDBのprojects.idを使ってコピー元、コピー先のidを調べておく。

コピー用プロシージャを登録

以下のreplicawiki2.sqlをローカルに保存して

$ mysql -p <redmine_database> < replicawiki2.sql

で登録する。

注意:コピー先にWikiページが存在する場合一度削除されます。

replicawiki2.sql
delimiter //
drop procedure if exists replicawiki2;
create procedure replicawiki2(projectid_from int, projectid_to int)
	begin
		declare done int default 0;
		declare last_id int;
		declare st_page varchar(255); 
		declare curso int;
		declare id_or int;
		declare id_nu int;
        declare wikid_from int;
        declare wikid_to int
		declare pages cursor for select id from wiki_pages wp where wp.wiki_id = wikid_from;
		declare copied_pages cursor for select id_original, id_new from aux_map;
		declare continue handler for not found set done = 1;

        -- get wiki id
        select wikis.id into wikid_from from wikis where wikis.project_id = projectid_from;
        select wikis.id into wikid_to   from wikis where wikis.project_id = projectid_to;

		-- caution this erase all current wiki pages of destination (to) wiki
        delete from attachments where container_type='wikipages' and container_id in (select id from wiki_pages where wiki_pages.wiki_id = wikid_to);
        delete from wiki_contents where id in (select id from wiki_pages where wiki_pages.wiki_id = wikid_to);
		delete from wiki_redirects where wiki_id = wikid_to ;
		delete from wiki_pages where wiki_pages.wiki_id = wikid_to ;
		
		open pages;
		
		-- fix wikis start page
		select wikis.start_page into st_page from wikis where id = wikid_from;
		update wikis set start_page = st_page where id = wikid_to;
	
		-- aux table to replicate the hierachy 
		drop table if exists aux_map;
		create table aux_map(id_original int, id_new int);
		
		-- copy redirects
		insert into wiki_redirects (wiki_id, `title`, redirects_to, created_on,redirects_to_wiki_id)
			select wikid_to as wiki_id, `title`, redirects_to, created_on ,wiki_to as redirects_to_wiki_id from wiki_redirects where wiki_id = wikid_from;
	
		-- copy all the wiki pages to origin to dest. and fill the auxiliary hierachy table  
		repeat
			fetch pages into curso;
			insert into wiki_pages (wiki_id, title, created_on, protected, parent_id)
				select wikid_to as wiki_id, wp.title, wp.created_on, wp.protected, wp.parent_id from wiki_pages wp where wp.id = curso limit 1;
			set last_id = last_insert_id();
			insert into aux_map (id_original, id_new)
				values(curso, last_id);	
		until done end repeat;
		
		set done = 0;
		open copied_pages;
		
		-- update hierachy and copy all the wiki contents.
		repeat 
			fetch copied_pages into id_or, id_nu;
			update wiki_pages set parent_id = id_nu where wiki_id = wikid_to and parent_id = id_or;
			insert into wiki_contents (page_id, author_id, `text`, `comments`, `updated_on`, `version`)
				select id_nu as page_id, author_id, `text`, `comments`, `updated_on`, `version` from wiki_contents wc where wc.page_id = id_or;
		until done end repeat;

        -- clone attachments
        insert into attachments(container_id,container_type,filename,disk_filename,filesize,content_type,digest,downloads,author_id,created_on,description,disk_directory)
        select
            aux_map.id_new,
            container_type,
            filename,
            concat('c',disk_filename),
            filesize,
            content_type,
            digest,
            downloads,
            author_id,
            created_on,
            description,
            disk_directory
        from `attachments`
        inner join aux_map on attachments.container_id = id_original
        where container_type='wikipage' ;

        -- print cannonical attachment copy script
        select
            concat('cp -n ',disk_directory ,'/', disk_filename,' ',disk_directory ,'/c', disk_filename,' ;') as pathto
        from `attachments`
        inner join aux_map on attachments.container_id = id_original
        where container_type='wikipage' ;

		close pages;
		close copied_pages;
		
		-- deleting auxiliary table
		drop table if exists aux_map;
	end
	//

実行

call replicawiki2(1,2); -- project_id=1から2へWikiの内容をコピー

これを実行するとコンソールに物理ファイルコピー用のコマンドが出力される

出力結果
cp -n 2021/03/150222162940_fb8abc027e5f98ab48c8b90bd550507d.png 2021/03/c150222162940_fb8abc027e5f98ab48c8b90bd550507d.png ;
cp -n 2021/03/150312113518_f257bd912a377aea98b7550787460168.png 2021/03/c150312113518_f257bd912a377aea98b7550787460168.png ;
# : 以下略

<redmine_home>/files で↑のコマンドを実行すればOK

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?