Let's Note SX4にFreeBSDをインストールする

Let's Note SX4FDKBPに入っているWindows 8.1 Pro 64bitの領域を縮小し、空き領域にFreeBSD 10.1を入れてデュアルブートするのが目的。

Windowsでの作業

Windowsアップデートとかしたくなるが、それはデュアルブートが成功してからにする。徒労に終る可能性がある。

リカバリーディスク

リカバリーディスク作成ユーティリティ」でリカバリーディスクを必ず作っておく。

高速スタートアップ解除

高速スタートアップを無効にする。コントロールパネル→電源オプション→電源ボタンの動作選択→高速スタートアップを有効にするのチェックを外す。「現在利用可能ではない設定を変更します」をクリックしないと外せない。
参考: http://www.eightforums.com/tutorials/6320-fast-startup-turn-off-windows-8-a.html

ecoモードにする

ecoモード(80%までしか充電しない; 電池の寿命が延びる)にする。

ディスクを縮小する

ディスクを縮小する。左下のWindowsアイコンのところで右クリック、「ディスクの管理」を選択。縮小する領域のサイズ(MB)を 350000 にする。思ったよりサイズが小さくできない場合は、いったんシステムの復元を無効化するとよい。

復元の無効化

システムのプロパティ→システムの保護、「保護設定」の「構成」→システム保護対象で「システムの保護を無効にする」を選択

終ったら元に戻しておく。

別のFreeBSDマシンでの作業

ブートイメージを使ってインストールメディアを作成するわけだが、
UEFIでブートしたいので、ファイル名にuefiという文字が入っているイメージファイルをとってくること。

CDではなぜかうまくいかなかったので、今回はUSBメモリースティックのための以下のイメージを使用した。
ftp://ftp.jp.freebsd.org/pub/FreeBSD/snapshots/amd64/amd64/ISO-IMAGES/10.1/FreeBSD-10.1-STABLE-amd64-20150520-r283161-uefi-memstick.img

 # dd if=Downloads/FreeBSD-10.1-STABLE-amd64-20150520-r283161-uefi-memstick.img of=/dev/da0 bs=64k

などとして書き込み。

Let's Noteでの作業

USBメモリを差した状態で起動し、起動時にF2を押してファームウェア設定画面に入る。
セキュアブートを無効にしておく。UEFIの起動順序にUSBメモリスティックの選択が現れるので、それを先頭に持ってくる。

すると、リブート後にインストーラが立ち上がるので、インストールを進める。パーティションを切るところで、ada0に

 freebsd-ufs 10GB /
 freebsd-ufs 50GB /usr
 freebsd-zfs 282GB

を作成。終了前にshellが開けるので、そこで適当なUSBメモリに/boot/boot1.efiをコピーしておく。終ったらリブートする。Windowsが立ち上がるが、心配ない。

コマンドプロンプトを右クリックして管理者として実行する。

 > bcdedit.exe /copy {bootmgr} /d "FreeBSD"

得られたUUIDをコピーしておく。
EFIパーティションをマウント。

 > mountvol.exe e: /S

中を見てディレクトリ作成。

 > dir e:\
 > mkdir e:\EFI\FreeBSD

USBメモリを差す(ドライブレターD:とする)

 > copy d:\boot1.efi e:\EFI\FreeBSD\
 > bcdedit /set {得られたUUID} path \EFI\FreeBSD\boot1.efi
 > bcdedit /set {fwbootmgr} displayorder {得られたUUID} /addlast

これでRebootしてF2を押してファームウェア設定画面に入ると、起動オプションにFreeBSDという選択肢が出てきます。これを先頭に持ってきます。設定を保存して終了します。すると、次回の起動時からは、FreeBSDが起動するようです。ファームウェア設定画面から直接Windows Boot Managerを選択したら、Windowsが起動します。やったね。

Windowsでの設定
FreeBSDでの設定

/etc/fstabに

 md /usr/obj mfs rw,async,-M,-s4g,noatime,late 0 0

を追加。

 # mount /usr/obj

/etc/groupのoperatorグループに自分のユーザ名を追加。

freebsd-zfsな領域を確認。

 # gpart show

ada0のカラムの番号が9なので、ada0p9がdeviceであると分かる。

tankというプールを作成。

 # zpool create tank /dev/ada0p9

いくつかファイルシステム作成。

 # zfs create tank/home
 # zfs create tank/data
 # zfs create tank/ports
 # zfs create tank/ports-distfiles

ホームディレクトリ移動

 # mv /home/* /tank/home/
 # zfs set mountpoint=/home tank/home

プロパティ設定

 # zfs set atime=off tank

portsディレクトリ関係マウントポイント設定

 # zfs set mountpoint=/usr/ports tank/ports 
 # mkdir /usr/ports/distfiles
 # zfs set mountpoint=/usr/ports/distfiles tank/ports-distfiles

portsディレクトリを一応取得。

 # portsnap fetch
 # portsnap extract

主にインストールしたもの。pkg install hogeでインストールできる。

  • sudo
  • zsh
  • lv
  • xfce
  • xlockmore
  • firefox
  • xorg
  • emacs24
  • tamago-emacs24
  • unzip
  • rubygem-netcdf
  • rubygem-ruby-dcl
  • netcdf-fortran
  • a2ps
  • w3m
  • cdrtools
  • conky
  • evince
  • ffmpeg
  • mplayer
  • gifsicle
  • gnupg
  • gnuplot
  • gv
  • inconsolata-ttf
  • ja-cannadic
  • ja-less+iso
  • ja-nkf
  • ja-scim-canna
  • ja-tex-ptex
  • lapack
  • lapack95
  • lha
  • linux_base-c6
  • papersize-default-a4
  • portlint
  • psutils
  • rsync
  • git
  • ruby-rd-mode.el
  • rubygem-pry
  • rubygem-narray_miss
  • rubygem-numru-misc
  • rubygem-numru-units
  • scim
  • scim-m17n
  • sharutils
  • tex-dvipdfmx
  • wget
  • wireshark
  • xfce4-mixer
  • xfce4-netload-plugin
  • xfce4-print
  • xfce4-systemload-plugin
  • xfce4-wm-themes
  • gimp
  • asymptote
  • bind-tools
  • dvd+rw-tools
  • gmake
  • icons-tango
  • icons-tango-extras
  • ja-font-ipa
  • ja-font-ipa-uigothic
  • ja-font-ipaex
  • ja-font-migu
  • ja-font-mplus
  • ja-font-mplus-ipa
  • ja-font-std
  • ja-font-vlgothic
  • rubygem-rdtool
  • smartmontools
  • xfce4-battery-plugin
  • xfce4-genmon-plugin
  • xf86-input-synaptics
  • xf86driproto
  • resourceproto

Rictyのインストール(パッケージがないので)。

 # cd /usr/ports/japanese/font-ricty/
 # make install

chshしてzshをログインシェルにしておく。

/usr/srcのチェックアウト。

 # cd /usr
 # rmdir src
 # svnlite co svn://svn0.us-west.FreeBSD.org/base/head /usr/src

/boot/loader.confを以下の内容で作成。

 #hint.psm.0.flags="0x6000"
 hint.psm.0.flags="0x2000"
 #hw.psm.synaptics_support="1"

 sound_load="YES"
 snd_hda_load="YES"
 sem_load="YES"
 
 uhci_load="YES"
 ehci_load="YES"
 xhci_load="YES"
 #hwpmc_load="YES" # cause panic
 coretemp_load="YES"

 # for bluetooth
 #ng_ubt_load="YES"

/etc/ttysの調整(ttyv5-v8までコメント)。

/etc/sysctl.confの内容を以下に設定。

 #hw.acpi.reset_video=1
 #hw.acpi.sleep_button_state=S3
 #hw.acpi.power_button_state=S3
 #hw.acpi.lid_switch_state=S3
 #hw.acpi.standby_state=S3
 debug.cpufreq.lowest=600
 hw.acpi.verbose=1

設定ファイルのコピーなど。

 /etc/wpa_supplicant.conf
 /etc/rc.conf
 /etc/X11/xorg.conf
 /etc/hosts
 /etc/make.conf
 /etc/mergemaster.rc
 /etc/periodic.conf
 /etc/portsnap.conf
 /etc/printcap
 /etc/rc.conf
 /etc/rc.local
 /etc/sysctl.conf
 /usr/local/etc/hal

次のコマンド

 # acpiconf -s 3

でsuspend(S3)できる. また, sysctl(8)で

 hw.acpi.power_button_state=S3

と設定すると, 電源スイッチをスライドさせるとsuspendする. また, 同じ操作をするかフタを閉めた状態から開けるとresumeする.

また, resume後に画面が真っ暗になるのでsysctl(8)で

 hw.acpi.reset_video=1

を設定し, resumeしたあとでリセットするようにすると昔の機種ではうまくいっていたのだが、この機種ではうまくいかない。フリーズしてしまう。

従ってsuspendは実質できないものと考えるべきだろう。hw.acpi_reset_video=0の状態では、(sshdを起動していれば)ネットワークログインはできる。画面が真っ暗なだけである。

デフォルトの/etc/devd.confにあるように,

 # User requested suspend, so perform preparation steps and then execute
 # the actual suspend process.
 notify 10 {
         match "system"          "ACPI";
         match "subsystem"       "Suspend";
         action "/etc/rc.suspend acpi $notify";
 };
 notify 10 {
         match "system"          "ACPI";
         match "subsystem"       "Resume";
         action "/etc/rc.resume acpi $notify";
 };

これによってsuspend/resume時に/etc/rc.suspend, /etc/rc.resumeを実行する. 無線LANをwpa_supplicant(8)を介して利用している場合には, /etc/rc.resumeの最後の方に書いてある

 #wpa_cli reassociate

のコメントを外しておくと, resume後に再接続を試みる.

CPU負荷が低いときにCPU周波数を落すように設定できる. これはcpufreq(4)とpowerd(8)によって行われる. cpufreqデバイス入りカーネル(例えばGENERIC)を用意するか, cpufreq.koをロードして, /etc/rc.confに

 powerd_enable="YES"

と書いておく. /etc/rc.d/powerd startなどとすれば起動.

稼働するCPU周波数の最低値を指定するには, MHz単位でsysctl(8)によって

 debug.cpufreq.lowest=600

などと設定する. この場合は負荷が低いときには600MHzで駆動する(see cpufreq(4)).

デフォルトでは, 温度が閾値より高くなった場合にCPU周波数を落すことで冷却を試みる(passive cooling). その閾値を例えば摂氏75.0に設定したいときはsysctl(8)で

 hw.acpi.thermal.user_override=1
 hw.acpi.thermal.tz0._PSV=75.0C

と設定しておく. hw.acpi.thermal.user_overrideを1に設定しないと, 二行目の変数の値を初期値から変更できない. 詳しくはacpi_thermal(4)を参照.

X.org

/boot/loader.confに

 hw.psm.synaptics_support="1"

と書いておく.

portsのxf86-intel-driverはバージョンが古くて(2.21.15)、ハードウェア(Intel HD Graphics 5500)をサポートしていない。2.99をとってくる。https://wiki.freebsd.org/Graphics/Ports%20development%20workflow に載ってる通り、

 > git clone https://github.com/freebsd/freebsd-ports-graphics.git
 > git branch -a

なんかずらずらと出る。その中に

  remotes/origin/xf86-video-intel-3.0

というのがあるはずである。このブランチに切替える。

 > git checkout -b xf86-video-intel-3.0 origin/xf86-video-intel-3.0
 > cd ~/github/freebsd-ports-graphics/x11-drivers/xf86-video-intel/
 > sudo make
 > sudo make install

これで、/etc/X11/xorg.confのDriverのところを"intel"にしたら起動するはずだが、No devices detected.というエラーが出るのでXが起動しない。

pkgからxf86-video-scfbをインストールして、/etc/X11/xorg.confのDriverのところを"scfb"にしたら動いた。

VGA出力

X.Org 7.7ではxrandr(1)コマンドで解像度や表示先を設定できる.

xrandr: Failed to get size of gamma for output default
Screen 0: minimum 1600 x 900, current 1600 x 900, maximum 1600 x 900
default connected 1600x900+0+0 0mm x 0mm
1600x900       0.00*

おそらくscfbドライバを使っているせいだろう、解像度を変えられないし、外部出力も使えないようだ。

ファンクションキーなど

(訂正, 2015/06/04)
/boot/kernel/acpi_panasonic.ko をロードすればよい。

F1,F2,F4,F7,F10はこれで使えるようである.
acpi_panasonic(4)によれば, 他のファンクションキー押下はdevdを使ってコマンドを適当に実行させるとよいらしい.

devdを使うには/etc/rc.confに

devd_enable="YES"

と書いておく. 設定ファイルはデフォルトで/etc/devd.confにある. 詳しくはファイルと
devd.conf(5)を参照.

acpi_panasonic(4)はreboot時にpanicすることがあるので、使用しない方がよいかもしれない。

無線LAN

Intel Dual Band Wireless-AC 7265が搭載されている。

カーネルモジュールの読み込み設定など

/boot/loader.confに以下を追記、、、すればよかったのだが、ハードウェアが新しすぎてサポートされていない。https://github.com/erikarn/freebsd-iwa を持ってきて試す。

 % git clone https://github.com/erikarn/freebsd-iwa.git

以下の変更を加える。そうしないとコンパイルが通らない。

 diff --git a/src/sys/dev/iwa/if_iwa.c b/src/sys/dev/iwa/if_iwa.c
 index f256e6e..bb3c72e 100644
 --- a/src/sys/dev/iwa/if_iwa.c
 +++ b/src/sys/dev/iwa/if_iwa.c
 @@ -455,7 +455,7 @@ iwa_start(struct ifnet *ifp)
  }
  
  static void
 -iwa_update_mcast(struct ifnet *ifp)
 +iwa_update_mcast(struct ieee80211com *ic)
  {
  
         printf("%s: called\n", __func__);

freebsd-iwa/src/sys/modules/iwaにてmakeする。カーネルモジュールをロードする。

 > sudo kldload ./if_iwa.ko

dmesgを確認。何も出力されない。ifconfigしても変化なし。動かないみたい。

Let's Note SX4にFreeBSDをインストールする(失敗)

Let's Note SX4FDKBPに入っているWindows 8.1 Pro 64bitの領域を縮小し、
空き領域にFreeBSD 10.1を入れてデュアルブートするのが目的。

Windowsでの作業

高速スタートアップ解除

高速スタートアップを無効にする。
http://www.eightforums.com/tutorials/6320-fast-startup-turn-off-windows-8-a.html

ecoモードにする

ecoモード(80%までしか充電しない; 電池の寿命が延びる)にする。

ディスクを縮小する

ディスクを縮小する。
思ったよりサイズが小さくできない場合は、いったんシステムの復元を無効化するとよい。

復元の無効化

システムのプロパティ→システムの保護

「保護設定」の「構成」→システム保護対象
で「システムの保護を無効にする」を選択

終ったら元に戻しておく。

別のFreeBSDマシンでの作業

ブートイメージを使ってインストールメディアを作成するわけだが、
UEFIでブートしたいので、ファイル名にuefiという文字が入っているイメージファイルをとってくること。

CDではなぜかうまくいかなかったので、今回はUSBメモリースティックのための以下のイメージを使用した。

ftp://ftp.jp.freebsd.org/pub/FreeBSD/snapshots/amd64/amd64/ISO-IMAGES/10.1/FreeBSD-10.1-STABLE-amd64-20150520-r283161-uefi-memstick.img

 # dd if=Downloads/FreeBSD-10.1-STABLE-amd64-20150520-r283161-uefi-memstick.img of=/dev/da0 bs=64k

などとして書き込み。

Let's Noteでの作業

USBメモリを差した状態で起動し、起動時にF2を押してファームウェア設定画面に入る。
UEFIの起動順序にUSBメモリスティックの選択が現れるので、それを先頭に持ってくる。

すると、リブート後にインストーラが立ち上がるので、インストールを進める。
終ったらリブートする。Windowsが立ち上がるが、心配ない。

コマンドプロンプトを右クリックして管理者として実行する。

 > bcdedit.exe /copy {bootmgr} /d "FreeBSD"

得られたUUIDをコピーしておく。
EFIパーティションをマウント。

 > mountvol.exe e: /S

中を見る

 > dir e:\
 > dir e:\EFI\Boot

これで、e:\EFI\Boot\bootx64.efiというファイルがあることが分かった。
というか、よく見たら https://wiki.freebsd.org/UEFI に書いてあった。

 > bcdedit /set {得られたUUID} path \EFI\Boot\bootx64.efi
 > bcdedit /set {fwbootmgr} displayorder {得られたUUID} /addlast

(いろいろあって、この間リブートしている)

 > diskpart.exe
 DISKPART> select disk 0
 DISKPART> list partition
 DISKPART> select partition 6
 DISKPART> list volume
 DISKPART> assign letter=U
 DISKPART> exit
 > bcdedit.exe /set {得られたUUID} device partition=U:

これでRebootしてF2を押してファームウェア設定画面に入ると、起動オプションにFreeBSDという選択肢が出てきます。
これを先頭に持ってきます。設定を保存して終了します。
すると、次回の起動時からは、FreeBSDが起動する、、、ようです。
ところが、今度はWindowsの起動に問題が起きて、
ファームウェア設定画面から直接Windows Boot Managerを選択しても、起動しなくなりました。
こまった。

evinceを使っているとき、pdf内のmp4をクリックしてmplayerを起動

evince で pdf を開いて、mp4へのリンクを開こうとしたら、evinceのウィンドウ内の上部に

外部のアプリケーションを起動できませんでした。
このファイルを扱うアプリケーションが登録されていません

と表示され、ターミナルに

** (evince:17114): WARNING **: ファイルのメタデータを設定中にエラー: そのようなファイルまたはディレクトリはありません

と表示された。

これを解決するため、以下のURLを参考にして設定した。
https://help.gnome.org/admin/system-admin-guide/stable/mime-types-custom-user.html.en

まずは、~/.local/share/mime/packages/video-mp4.xml を以下のように作成。

<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
  <mime-type type="video/mp4">
    <comment>MP4</comment>
    <glob pattern="*.mp4"/>
  </mime-type>
</mime-info>

次に、~/.local/share/applications/mplayer.desktopを以下のように作成。

[Desktop Entry]
Type=Application
MimeType=video/mp4
Name=MP4
Exec=mplayer

以下のコマンドを実行。

$ update-mime-database ~/.local/share/mime
$ update-desktop-database ~/.local/share/applications

確認。

$ gvfs-info movie.mp4 | grep "standard::content-type"
  standard::content-type: video/mp4
$ gvfs-mime --query video/mp4
'video/mp4' 用の標準アプリケーション: mplayer.desktop
登録されているアプリケーション:
	mplayer.desktop
推奨されているアプリケーション:
	mplayer.desktop

emacs tex-modeの数式表示

emacstex-modeの数式表示で、$x_t$などと入力すると、tが字下げされて小さいフォントで表示されるのが気に入らなかったので、以下のように~/.emacsに書いて対処。

(custom-set-variables '(tex-suscript-height-ratio 1.0))
(custom-set-variables '(tex-font-script-display '(0.0 0.0)))

FreeBSD portsのStageDir

この記事はディストリビューション/パッケージマネージャー Advent Calendar 2013の7日目の記事です。

FreeBSDports maintainerの方向けの記事です。
最近、FreeBSDにStageDirというものが導入されました

これまでは、パッケージを作成する際には、いったん対象のportsをインストールしてからそのインストールされたものを元にパッケージを作成するという流れでした。

StageDir導入後はStageディレクトリにいったんインストールし、パッケージを作成してからそのパッケージをインストールする、という流れになります。

StageDir非対応のportsMakefileにはNO_STAGE=yesという行があります。

詳しくはhttps://wiki.freebsd.org/ports/StageDirを参照してください。(これ、wikiのトップページからたどれないんですよね、、、)

大方の人は、{pre,do,post}-installするときにStageDirにインストールする、つまり、${PREFIX}などの前に${STAGEDIR}を付ける、ということを覚えておけば良いと思います。

メリットとしては、(1)pkg-plistが作りやすくなる:

$ make makeplist

(2)既に作ったパッケージのpkg-plist漏れがチェックできる:

$ make check-orphans

あたりが挙げられるでしょうか(他にもあったら教えてください)。(一般ユーザでもパッケージが作れるようになりますが、これはメリットなのか?)

StageDir対応portsの作成テストは

$ make stage && make check-orphans && make package

で行います。

実際にStageDir対応したportsとして、ports/science/cdcl/Makefileのdiffを見てみましょう。

diff -urN cdcl.orig/Makefile cdcl/Makefile
--- cdcl.orig/Makefile	2013-10-28 16:54:55.462827000 +0900
+++ cdcl/Makefile	2013-11-29 00:26:57.613262652 +0900
@@ -2,7 +2,7 @@
 # $FreeBSD: head/science/cdcl/Makefile 327767 2013-09-20 22:48:30Z bapt $
 
 PORTNAME=	cdcl
-PORTVERSION=	5.4.7
+PORTVERSION=	5.4.8
 CATEGORIES=	science graphics
 MASTER_SITES=	http://www.gfd-dennou.org/arch/dcl/ \
 		http://dennou-h.gfd-dennou.org/arch/dcl/ \
@@ -13,17 +13,17 @@
 COMMENT=	Scientific graphic library for geoscience
 
 USES=		pkgconfig
-USE_GCC=	any
+#USE_GCC=	any
 USE_XORG=	x11 xext
 USE_GNOME=	gtk20 gdkpixbuf2
 GNU_CONFIGURE=	yes
-CONFIGURE_ARGS=	--prefix=${PREFIX} --exec-prefix=${PREFIX} --with-x --enable-shared
+GNU_CONFIGURE_PREFIX=	${STAGEDIR}${PREFIX}
+CONFIGURE_ARGS=	--with-x --enable-shared
 
 PLIST_SUB=	DCL_VERSION=${PORTVERSION:S/.//g}
 
 MAKE_JOBS_UNSAFE=	yes
 
-NO_STAGE=	yes
 .include <bsd.port.pre.mk>
 
 BINARIES=	cdclcmap cdclclr cdcldate cdcldbs cdclexec cdclfont \
@@ -38,16 +38,16 @@
 
 post-install:
 .for i in ${BINARIES}
-	${STRIP_CMD} ${PREFIX}/bin/${i}
+	${STRIP_CMD} ${STAGEDIR}${PREFIX}/bin/${i}
 .endfor
 .if !defined(NOPORTEXAMPLES)
-	@${MKDIR} ${EXAMPLESDIR}
-	(cd ${WRKSRC}/demo/ && ${COPYTREE_SHARE} \* ${EXAMPLESDIR})
+	@${MKDIR} ${STAGEDIR}${EXAMPLESDIR}
+	(cd ${WRKSRC}/demo/ && ${COPYTREE_SHARE} \* ${STAGEDIR}${EXAMPLESDIR})
 .endif
 .if !defined(NOPORTDOCS)
-	@${MKDIR} ${DOCSDIR}
+	@${MKDIR} ${STAGEDIR}${DOCSDIR}
 .for i in ${PORTDOCS}
-	${INSTALL_DATA} ${WRKSRC}/${i} ${DOCSDIR}/
+	${INSTALL_DATA} ${WRKSRC}/${i} ${STAGEDIR}${DOCSDIR}/
 .endfor
 .endif

こんな感じです。post-installの箇所に${STAGEDIR}が随所に加えられているのが見て取れるでしょうか。

ところで、GNU_CONFIGURE_PREFIXというのが加わっていますが、これはこれまでのメンテナのミスで(一体誰だ(私だ))、GNU configureで--prefix指定したい場合にはCONFIGURE_ARGSには書かずにGNU_CONFIGURE_PREFIXに書くべきだったのでした。

特に明示されてはいないようですが、今後はNO_STAGE=yesなportsは徐々に減らす意向と思われます。みなさんのメンテされているportsも徐々にStageDir対応していきましょう。

hiki 1.0.0 続き

hiki 1.0.0に移行するために、CVSリポジトリそのものを移行する方法があります。そのためのスクリプトを書きました。

#!/usr/bin/env ruby

$LOAD_PATH.unshift "."

require "optparse"
require "pathname"
require "fileutils"
require "nkf"
require "hiki/util"
require "hiki/config"

def convert(cvsroot_path, input_encoding, output_encoding, nkf)
  Dir.glob("#{cvsroot_path}/hiki/*,v").each do |old_file_fullpath|
    begin
      dir = File.dirname(old_file_fullpath)
      old_file = File.basename(old_file_fullpath).chop.chop
      new_file = Hiki::Util.escape(encode(Hiki::Util.unescape(old_file),
                                          input_encoding, output_encoding, nkf))

      print "#{old_file} => #{new_file} "
      cont = nil
      File.open("#{dir}/#{old_file},v", "r:#{input_encoding}") do |fin|
        cont = fin.read.force_encoding(input_encoding)
      end
      FileUtils.rm_f("#{dir}/#{old_file},v")
      File.open("#{dir}/#{new_file},v", "w:#{output_encoding}") do |fout|
        fout.write encode(cont, input_encoding, output_encoding, nkf)
      end
      puts "OK."
    rescue StandardError => ex
      puts " NG."
      puts "#{ex.class}: #{ex.message}"
      puts ex.backtrace
    end
  end
end

def encode(text, input_encoding, output_encoding, nkf)
  if nkf
    NKF.nkf("-m0 --ic=#{input_encoding} --oc=#{output_encoding}", text)
  else
    text.dup.encode!(output_encoding, input_encoding, :invalid => :replace, :und
ef => :replace)
  end
end

def main(argv)
  parser = OptionParser.new
  cvsroot_path = nil
  input_encoding = nil
  output_encoding = nil
  nkf = false
  parser.on("-c", "--cvsroot-directory=DIR", "Specify the cvsroot directory"){|d
ir|
    cvsroot_path = Pathname(dir).realpath
  }
  parser.on("-i", "--input-encoding=ENCODING", "Specify the input encoding"){|en
coding|
    input_encoding = Encoding.find(encoding)
  }
  parser.on("-o", "--output-encoding=ENCODING", "Specify the output encoding"){|
encoding|
    output_encoding  = Encoding.find(encoding)
  }
  parser.on("--nkf", "Use NKF (default: no)"){
    nkf = true
  }

  begin
    parser.parse!(argv)
  rescue
    STDERR.puts $!.class.to_s
    STDERR.puts $!.message
    exit 1
  end

  convert(cvsroot_path, input_encoding, output_encoding, nkf)
end

if __FILE__ == $0
  main(ARGV)
end

構造はほとんどconvert.rbから借りてきました。
これで変換した後でチェックアウトすれば更新完了です。過去の履歴も見られるし、快適。

hiki 1.0.0

hiki 1.0.0に移行するために、hiki/tool/convert.rbを使って既存データを変換してみました。結果。

ArgumentError: invalid byte sequence in UTF-8
/usr/share/hiki/hiki/util.rb:72:in `gsub'
/usr/share/hiki/hiki/util.rb:72:in `escape'
./tool/convert.rb:44:in `block in convert'
./tool/convert.rb:40:in `each'
./tool/convert.rb:40:in `convert'
./tool/convert.rb:120:in `main'
./tool/convert.rb:125:in `<main>'
 NG.

と怒られます。

--- tool/convert.rb.orig	2013-11-06 03:36:46.000000000 +0900
+++ tool/convert.rb	2013-11-06 03:33:00.000000000 +0900
@@ -39,7 +39,7 @@
   db = database_class.new(config)
   db.pages.each do |page|
     begin
-      old_page = page
+      old_page = page.force_encoding(input_encoding)
       new_page = encode(old_page, input_encoding, output_encoding, nkf)
       print "#{Hiki::Util.escape(old_page)} => #{Hiki::Util.escape(new_page)}"
       old_text = db.load(old_page)

この変更でうまく動きました(2013/11/17:この変更はhikiに取り込まれました)。

次のURLにインストールログをまとめました。
http://www.gfd-dennou.org/member/murashin/memo/hiki-1.0.0-install-log.html

既知の問題として、検索に失敗することがあることがわかっています。これは、データ変換に失敗した場合のみ起こります。メタデータ(info.db)から変換に失敗したデータを削除すればOKです。