2010-10-30

Redmine の Wiki に添付したファイルを移動させる

Redmine の Wiki にはファイルを添付する機能がある。ところが、Wiki の名前を変更すると、添付したファイルは消えてしまう。正確には、古い Wiki 名にファイルが紐付けされていて、新しい Wiki 名へと追随しない。

現状、スマートな解決策はない。泥臭いけれど、Wiki を管理している DB を直接いじるしかない。本エントリーでは、MySQL を使っているとして Wiki に添付したファイルを移動させる手順を説明する。

database.yml

使っている database.yml を示す。

/var/lib/redmine$ cat config/database.yml
# MySQL (default setup).  Versions 4.1 and 5.0 are recommended.
#
# Get the fast C bindings:
#   gem install mysql
#   (on OS X: gem install mysql -- --include=/usr/local/lib)
# And be sure to use new-style password hashing:
#   http://dev.mysql.com/doc/refman/5.0/en/old-client.html

production:
  adapter: mysql
  database: redmine
  host: localhost
  username: redmine
  password: foo
  encoding: utf8

adapter は mysql。database や username、password は自分の環境に合った値に設定されたし。

Backup DB

DB を下手にいじって壊してしまってもいけないので、作業前にはバックアップを取っておこう。

/var/lib/redmine$ /usr/bin/mysqldump -u -p | gzip < redmine_`date +%y_%m_%d`.gz 

MySQL をいじる

ここでは実際に「GitWindows」という Wiki ページを「MsysGitInstall」という名前に変更した場合の作業手順を示す。ちなみに、「GitWindows」という Wiki を「MsysGitInstall」にリネームした後、改めて「GitWindows」という Wiki ページを作成してある。やりたかったのは、「GitWindows」という Wiki が大きくなりすぎたので、一部を「MsysGitInstall」という Wiki に切り出す作業。

次のコマンドを実行して、MySQL が管理している Redmine の DB をいじる。オプションとして与える user, password, host は database.yml の値を使う。

/var/lib/redmine$ mysql --user=redmine --password=foo -h localhost redmine

以降、mysql のプロンプトでの操作になる。

まずはどんな DB があるか確認してみやう。

mysql< show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema | 
| redmine            | 
+--------------------+
2 rows in set (0.00 sec)

redmine という DB があるのが確認できる。これから、この DB をいじっていく。

mysql< use redmine;
Database changed

作業 DB を「redmine」に切り替えたら、どんなテーブルがあるか確認しやう。

mysql< show tables;
+-------------------------------------+
| Tables_in_redmine                   |
+-------------------------------------+
| attachments                         | 
| auth_sources                        | 
| boards                              | 
| changes                             | 
| changesets                          | 
| changesets_issues                   | 
| comments                            | 
| custom_fields                       | 
| custom_fields_projects              | 
| custom_fields_trackers              | 
| custom_values                       | 
| documents                           | 
| enabled_modules                     | 
| enumerations                        | 
| groups_users                        | 
| issue_categories                    | 
| issue_relations                     | 
| issue_statuses                      | 
| issues                              | 
| journal_details                     | 
| journals                            | 
| member_roles                        | 
| members                             | 
| messages                            | 
| news                                | 
| open_id_authentication_associations | 
| open_id_authentication_nonces       | 
| plugin_schema_info                  | 
| projects                            | 
| projects_trackers                   | 
| queries                             | 
| repositories                        | 
| roles                               | 
| schema_migrations                   | 
| settings                            | 
| time_entries                        | 
| tokens                              | 
| trackers                            | 
| user_preferences                    | 
| users                               | 
| versions                            | 
| watchers                            | 
| wiki_content_versions               | 
| wiki_contents                       | 
| wiki_pages                          | 
| wiki_redirects                      | 
| wikis                               | 
| workflows                           | 
+-------------------------------------+
48 rows in set (0.01 sec)

この通り、48 のテーブルが見つかった。wiki の一覧を見るには、wiki_pages テーブルを参照する。全てを select すると量が多くて大変になるだらうから、like 演算子等を使って絞り込みをしやう。ここではタイトルに「GIT」が含まれている Wiki を抽出してみる。

mysql< select * from wiki_pages where title like '%GIT%';
+----+---------+----------------+---------------------+-----------+-----------+
| id | wiki_id | title          | created_on          | protected | parent_id |
+----+---------+----------------+---------------------+-----------+-----------+
| 26 |       2 | GitAdmin       | 2009-08-20 11:19:13 |         0 |         3 | 
| 27 |       2 | GitProxy       | 2009-08-20 11:29:46 |         0 |         3 | 
| 28 |       2 | GitCommitLog   | 2009-08-20 11:38:24 |         0 |         3 | 
| 29 |       2 | GitRepo        | 2009-08-20 11:59:23 |         0 |         3 | 
| 30 |       2 | GitIntro       | 2009-08-20 12:03:18 |         0 |         3 | 
| 39 |       2 | GitWindows     | 2009-10-08 11:14:10 |         0 |         3 | 
| 41 |       2 | GitConfig      | 2009-10-21 11:09:13 |         0 |        30 | 
| 45 |       2 | EclipseGit     | 2009-11-05 14:32:43 |         0 |         3 | 
| 46 |       2 | MsysGitInstall | 2009-11-05 17:31:37 |         0 |        39 | 
+----+---------+----------------+---------------------+-----------+-----------+
9 rows in set (0.00 sec)

この通り、9 つの Wiki が見つかった。ここで、移動元の Wiki「GitWindows」の id が 39 であること、移動先の Wiki「MsysGitInstall」の id が 46 であることをメモしておこう。

次は attachments テーブルを見てみたい。ただこのテーブルの構成が分からない。未知のテーブルに出会ったら desc コマンドでテーブルの詳細を確認する。

mysql< desc attachments;
+----------------+--------------+------+-----+---------+----------------+
| Field          | Type         | Null | Key | Default | Extra          |
+----------------+--------------+------+-----+---------+----------------+
| id             | int(11)      | NO   | PRI | NULL    | auto_increment | 
| container_id   | int(11)      | NO   | MUL | 0       |                | 
| container_type | varchar(30)  | NO   |     |         |                | 
| filename       | varchar(255) | NO   |     |         |                | 
| disk_filename  | varchar(255) | NO   |     |         |                | 
| filesize       | int(11)      | NO   |     | 0       |                | 
| content_type   | varchar(255) | YES  |     |         |                | 
| digest         | varchar(40)  | NO   |     |         |                | 
| downloads      | int(11)      | NO   |     | 0       |                | 
| author_id      | int(11)      | NO   | MUL | 0       |                | 
| created_on     | datetime     | YES  | MUL | NULL    |                | 
| description    | varchar(255) | YES  |     | NULL    |                | 
+----------------+--------------+------+-----+---------+----------------+
12 rows in set (0.01 sec)

12 のカラムがあることが分かった。

各々のカラムの役割を見てみたい。そこで適当なファイルを選んで、カラムと値の対応関係を見てみる。

mysql< select * from attachments where filename like 'msysgit%-01.png';
+----+--------------+----------------+------------------------+-------------------------------------+----------+--------------+----------------------------------+-----------+-----------+---------------------+------------------------------------+
| id | container_id | container_type | filename               | disk_filename                       | filesize | content_type | digest                           | downloads | author_id | created_on          | description                        |
+----+--------------+----------------+------------------------+-------------------------------------+----------+--------------+----------------------------------+-----------+-----------+---------------------+------------------------------------+
| 42 |           39 | WikiPage       | msysgit-install-01.png | 091008113037_msysgit-install-01.png |    22520 | image/png    | af7ca8345cb3477b3ee7c59327918779 |         0 |         3 | 2009-10-08 11:30:37 | MsysGit インストール画面 1         | 
+----+--------------+----------------+------------------------+-------------------------------------+----------+--------------+----------------------------------+-----------+-----------+---------------------+------------------------------------+
1 row in set (0.00 sec)

どうやら、添付ファイルの ID が「id」、そのファイルが添付されている Wiki の ID が「container_id」、そして添付ファイル名が「filename」というカラム名で現されているらしい。

移動させたい添付ファイルは「msysgit-install-*.png」なので、こんな SQL 文を書いてみる。

mysql< select id,container_id,filename from attachments where filename like 'msysgit%';
+----+--------------+------------------------+
| id | container_id | filename               |
+----+--------------+------------------------+
| 42 |           39 | msysgit-install-01.png | 
| 43 |           39 | msysgit-install-02.png | 
| 44 |           39 | msysgit-install-03.png | 
| 45 |           39 | msysgit-install-09.png | 
| 46 |           39 | msysgit-install-04.png | 
| 47 |           39 | msysgit-install-05.png | 
| 48 |           39 | msysgit-install-06.png | 
| 49 |           39 | msysgit-install-07.png | 
| 50 |           39 | msysgit-install-08.png | 
| 55 |           39 | msysgit-install-11.png | 
+----+--------------+------------------------+
10 rows in set (0.00 sec)

この通り、添付ファイルは 39 番の Wiki に貼り付いている。これを 46 番の Wiki へ移動させたい。やるべきことは、SQL で container_id の値を変えるだけ。

mysql< update attachments set container_id = 46 where filename like 'msysgit%';
Query OK, 10 rows affected (0.01 sec)
Rows matched: 10  Changed: 10  Warnings: 0

Query は成功したと言っている。実際に成功したか確かめてみやう。

mysql< select id,container_id,filename from attachments where filename like 'msysgit%';
+----+--------------+------------------------+
| id | container_id | filename               |
+----+--------------+------------------------+
| 42 |           46 | msysgit-install-01.png | 
| 43 |           46 | msysgit-install-02.png | 
| 44 |           46 | msysgit-install-03.png | 
| 45 |           46 | msysgit-install-09.png | 
| 46 |           46 | msysgit-install-04.png | 
| 47 |           46 | msysgit-install-05.png | 
| 48 |           46 | msysgit-install-06.png | 
| 49 |           46 | msysgit-install-07.png | 
| 50 |           46 | msysgit-install-08.png | 
| 55 |           46 | msysgit-install-11.png | 
+----+--------------+------------------------+
10 rows in set (0.00 sec)

見事、添付したファイルが 46 番の Wiki に移った。

後は、ウェブ・ブラウザーを開いて Redmine の中で本当に添付ファイルが移動しているか確認しませう。

おしまい。

No comments:

Post a Comment