Mercurial をポータブル化する方法

概要

Mercurial をUSBメモリなどで持ち運べるよう、ポータブル化します。

目標

  • ファイルサイズをできる限り小さく
  • レジストリを汚さない
  • 使用PCにファイルを残さない

使用したのは、TortoiseHg 1.1.2 (tortoisehg-1.1.2-hg-1.6.2-x86.msi) (Mercurial 1.6.2)

インストール

インストーラの展開

Mercurial SCM か、 TortoiseHg > Download から、最新版の msi ファイルをダウンロードします。私が使ったのは、 tortoisehg-1.1.2-hg-1.6.2-x86.msi。

msi を展開するには、コマンドプロンプトで下記のように入力する。

msiexec.exe /a tortoisehg-1.1.2-hg-1.6.2-x86.msi targetdir="展開先フォルダ" /qn

展開された中で必要なのは、 \PFiles\TortoiseHg\ フォルダだけなので、他は削除してもかまわない。(もし、Visual C++ 2008 SP1 再頒布可能パッケージがインストールされていない環境でも使う可能性があるのなら、 Windows\system32\msvcr90.dll、Windows\system32\msvcm90.dll、Windows\system32\msvcp90.dll は残しておく。特に msvcr90.dll)

不要ファイルの削除

\PFiles\TortoiseHg\ フォルダの中から不要な ファイル/ディレクトリ を削除する。

  • 不要ディレクトリ
\contrib
\diff-scripts
\doc
\gtk\share\locale
\help
\hgrc.d
\i18n
\icons\svg
\locale
  • 不要ファイル
COPYING.txt
docdiff.exe
extension-versions.txt
kdiff3.exe
Pageant.exe
ThgShellx86.dll
TortoiseHgOverlayServer.exe
TortoisePlink.exe

もちろんこれは私が不要と考えたものなので、削除するものは利用者自身で適宜選択してほしい。

library.zip の圧縮

library.zip の中には、動作に必須のファイルが入っていて、拡張子からも分かるだろうが、 ZIP で圧縮されている。 しかし、これは圧縮レベルが無圧縮になっているので、圧縮というよりは tar だ。これを圧縮することによって、必要ファイルサイズを少なくできる。

library.zip をフォルダを作成して解凍し、そのファルダ配下を 7-Zip 9.15 beta で圧縮した。書庫形式:zip、圧縮レベル:超圧縮、圧縮メソッド:Deflate という設定。

※ ただし、これによってパフォーマンスが多少落ちるのではないかと思われる。が、最近の PC であれば、体感できるほどの差はないだろう。

PEファイル (exe, dll) の圧縮

\TortoiseHg\ フォルダ配下にあるすべての exe, dll を UPX 圧縮する。

UPX 3.05w を使った。オプションは、

--best --overlay=strip

おそらく、なぜ library.zip の中を UPX で圧縮しないのかと思われる方もいらっしゃるだろうが、圧縮してしまうと、

abort: no username supplied (see "hg help config")

とエラーが出て、commit 出来なくなった(もちろん username は設定済み)からだ。 upx のオプションを

-1 --compress-exports=0 --compress-resources=0 --strip-relocs=0 --compress-icons=0

に変更してみても無理だったので、中にUPX圧縮すると駄目なファイルがあるのだろう。探すのはさすがに面倒だったし、bestオプション + zipしても、それほどサイズが縮まなかったのでやめた。

USBメモリなどに移動

これで一応、一区切りついたので、 \TortoiseHg\ フォルダを、 Mercurial などにリネームしてUSBメモリなど、好きな場所に移動させる。

便利に使う為に

Mercurial.ini のテンプレートを作成する

Mercurial.ini の中では、絶対パス(と、環境変数を使ったパス)しか使えないようで、ポータブルとして使うのは不便。 よって、テンプレートを作り、それを元に、実行時に Mercurial.ini を動的生成するようにする。もし相対パスで指定する方法をご存知の方は、是非教えていただきたい。

ファイル名は何でも構わないが、ここでは Mercurial.ini.Template という名前にした。中身は、通常使っている Mercurial.ini をコピーする。
そして、テンプレート中の絶対パス指定している箇所のドライブレター部分を、「変換-ドライブレター」などにする。
例えば、

[ui]
editor = Z:\Soft\Editor\EmEditor\EmEditor.exe /sp /nr /cp 65001 /cps 65001 /ss-
;editor = Z:\Soft\Editor\sakura\sakura.exe -CODE=4 -GROUP=50
;editor = Z:\Soft\Editor\xyzzy\xyzzy.exe

ignore = Z:\Mercurial\hgignore.ini

[extensions]
fixutf8 = Z:\Mercurial\hg-fixutf8\fixutf8.py

このような設定箇所があった場合、ドライブレターである 「Z:」 を 「変換-ドライブレター」 に置換して保存しておく。

[ui]
editor = 変換-ドライブレター\Soft\Editor\EmEditor\EmEditor.exe /sp /nr /cp 65001 /cps 65001 /ss-
;editor = 変換-ドライブレター\Soft\Editor\sakura\sakura.exe -CODE=4 -GROUP=50
;editor = 変換-ドライブレター\Soft\Editor\xyzzy\xyzzy.exe

ignore = 変換-ドライブレター\Mercurial\hgignore.ini

[extensions]
fixutf8 = 変換-ドライブレター\Mercurial\hg-fixutf8\fixutf8.py

上記のようになる。もちろん、 「変換-ドライブレター」 などというアホな文字列でなくとも構わないが、万が一にも誤爆があると問題なので、iniには使わないような 文字/文字列 にすることが望ましい。

Mercurial.ini の動的生成等の処理を行う バッチファイル/スクリプト(WSH) の作成

上記 Mercurial.ini.Template を元に、Mercurial.ini を生成する バッチファイル/スクリプト(WSH) を作成する。

@if(0)==(0) echo off
set PATH=%~dp0;%PATH%;

:: fixutf8用
set HGENCODING=utf-8

:: お好みで
cd /d "%~dp0_Project"

CScript.exe //Nologo //E:JScript "%~f0" %*

:: プロセスが2つになるので、そのままcmd /kなどを実行しない
:: startコマンドでタイトルを変更しない。コンソールの設定を継承しないから
start %ComSpec% /U /K "title Mercurial Portable (%~dp0)"

goto :EOF
@end

/** JScript **/
var FSO = new ActiveXObject('Scripting.FileSystemObject'),
    rPath = FSO.GetParentFolderName(WScript.ScriptFullName);

(new ActiveXObject('WScript.Shell')).CurrentDirectory = rPath; // バッチ中の処理によっては不要

var oFile_Template = FSO.OpenTextFile('Mercurial.ini.Template'),
    ini = oFile_Template.ReadAll();
oFile_Template.Close();

var oFile_ini = FSO.CreateTextFile('Mercurial.ini', true);
oFile_ini.Write(ini.replace(/変換-ドライブレター/g, FSO.GetDriveName(rPath)));
oFile_ini.Close();

上を、bat あるいは cmd ファイルとして Mercurial ディレクトリに保存する。もちろん、ファイル名や置換用文字列を変更している場合や、その他の環境変数を設定したい場合などは、それに合わせ適宜変更する。

上記は、バッチファイルと JScript を纏めて1つのファイルにしているが、すべて WSH (JScript / VBScript) で書いてしまってもいい。また、「HGENCODING=utf-8」 は、 fixutf8 用に書いているものなので、使用していないなら消したほうがいいだろう。

このスクリプトは、他のソフトにも使える

ちなみにこの方法は、他の、設定ファイル中で絶対パス指定しか出来ないようなソフトをポータブル化する時にも使えます。

TortoiseHg の設定の保存先を変更する

TortoiseHg (hgtk.exe) は、%APPDATA%\TortoiseHg\ にダイアログの位置や状態などを保存する。なぜかこれは ini や環境変数の %APPDATA% などでは変更できないようなので、 TortoiseHg のソースに手を入れる。 %APPDATA%\TortoiseHg\ にファイルが残っても構わないのであれば、ここを実行する必要はない。

TortoiseHg > Download for Source Packagesから、対応するバージョンのSource CodeをDLする。使用しているのは TortoiseHg 1.1.2 なので、tortoisehg-1.1.2.tar.gz をDL。

--- tortoisehg/util/settings.py    Thu Jan 15 17:52:48 1970
+++ tortoisehg/util/settings.py    Thu Jan 15 17:52:48 1970
@@ -104,8 +104,9 @@
             try:
                 import pywintypes
                 try:
-                    from win32com.shell import shell, shellcon
-                    appdir = shell.SHGetSpecialFolderPath(0, shellcon.CSIDL_APPDATA)
+                    # from win32com.shell import shell, shellcon
+                    # appdir = shell.SHGetSpecialFolderPath(0, shellcon.CSIDL_APPDATA)
+                    appdir = os.environ['HGHOME']
                 except pywintypes.com_error:
                     appdir = os.environ['APPDATA']
             except ImportError:

上記のように変更した settings.py を、 library.zip の中の settings.pyo の代わりに入れる。(settings.pyo は削除する。)これで、環境変数の %HGHOME%\TortoiseHg\ のパスに設定を保存するようになったので、上で作成したバッチファイルを変更する。具体的には、

set HGHOME=%~dp0

をバッチ中に挿入する。

完成

動作確認

以上で完成となる。

当然、本番で使う前に適当に使ってみて動作を確認しておいたほうがいいだろう。こちらでは、 hg.exe と hgtk.exe で、 init, add, commit, rollback, clone, push, pull, update, serve などが問題なく使えることは確認済み。

最終的なファイルサイズなど

私の環境では、総サイズ 15.1 MiB で、 mercurial-tree.txt となった。これを実行していれば、レジストリ / ファイル も残さない。

\gtk\ / library.zip を整理すればもう少し削れそう。

ちなみに、デフォルトインストール(インストーラを実行して、何も考えずに Next ボタンを連打)だと、 \TortoiseHg\ ディレクトリだけで、 58.4 MiB (61,249,553 bytes) だった。

Mercurial 単体版 (mercurial-1.6.2.msi) の方だと、 \Mercurial\ ディレクトリだけで、 17.5 MiB (18,373,673 bytes)。

その他

\templates\ ディレクトリ

hg serve には、\templates\ ディレクトリが必要。 serve コマンドを使用しないなら不要。

Mercurial.ini 中の環境変数を使ったパス指定法

set HOME=%~dp0
ignore = ${HOME}\hgignore.ini
fixutf8 = ${HOME}\hg-fixutf8\fixutf8.py
editor = ${ProgramFiles}\hoge\hoge.exe

%~dp0 時、 ${HOME} 直後の \ は本来不要なのだが、ぱっと見分かり難いので記述している。(あっても問題はない)

%HGHOME% を設定しているのであれば、 ${HGHOME} を使っての指定でも構わないが、 editor や merge ツールは、通常、別ディレクトリにあるだろうから、動的生成スクリプトで変換した方がいいだろう。

hgtk.exe が不要であれば

\gtk\ , \icons\ ディレクトリが不要になるので、更にサイズを削減できる。2つ + hgtk.exe 削除で、3.60 MiB減。

hg-fixutf8 使用時

win32helper.py 変更。

Fedora Linux 13 (Goddard)
Mercurial 1.6.2
TortoiseHg 1.1.2
Ubuntu Linux 10.04 (Lucid Lynx)
Mercurial 1.4.3
TortoiseHg 0.9.2

これら環境上で hg serve した Mercurial と、日本語ファイル名等のやり取りも問題ない。逆に、 Windows 上で hg serve した Mercurial と、上記環境とのやり取りも試したが問題なかった。

だがまぁ、日本語なんて使わないに越したことはない。

QLOOK ANALYTICS Counter