rcmdnk's blog
Last update

THE STOW AWAY CAT, Book 2 of The Adventures of Jimbo Series: An Illustrated Childrens Book (English Edition)

ユーザー権限で必要なパッケージをローカルインストールするまとめスクリプト の中で Stow を使ってパッケージを管理インストールしてましたが、 ちょっとStowには問題があってそれを中で無理やり解決していました。

その辺を XStow というStowの代替コマンドが上手く処理してくれるようなのでそちらを 試してみました。

Sponsored Links

Stowの問題点

Stowを使うときは、まず、configureコマンドなどで、 ~/usr/local/stow/screen-4.2.1/ 等の様にstowというディレクトリの下の パッケージの名前を付けたディレクトリを指定して 各パッケージをインストールします。

その後、stowディレクトリで

$ stow screen-4.2.1

等とすると、stow/screen-4.2.1/bin/screen等へのリンクが bin/screenなどへ貼られます。

この際、ディレクトリは、もし他のパッケージと共通するものがない場合、 ディレクトリ単位でリンクが貼られます。

上のbin/screenの場合も、一番最初にインストールするときなどは binへのリンクが貼られるだけです。

その後、他のパッケージがbinを使う時には、 リンクが一旦消されディレクトリが作られ、 その中に今度は中身のリンクが作られます。

この様に、ディレクトリ単位では同じ物があっても勿論良いわけですが、 一方、ファイルの同じ物がある場合は競合してインストールに失敗します。

これが良く起こるのがshare/info/dirというファイルです。

このファイルはinfoコマンド等で見れる情報を読み取るのに使われるものですが、 各パッケージこの同じdirを使います。

make installする際には、その辺、もしdirがあると良しなに マージしてくれるみたいですが1、 Stowでは単にファイルを見てるだけなのでそのような事は出来ません。

そこで、前回のスクリプトの中では、 特にこのdirは要らないだろう、ということで

1
2
3
4
5
6
7
8
9
10
11
stow_wrap () {
  # To avoid dir/info conflict, just delete the previous info...
  if [ -f $1/share/info/dir ];then
    rm -f ../share/info/dir
  fi
  $STOWCMD $1
  if [ $? -ne 0 ];then
    echo FAITAL ERROR: failed to install $1
    exit 1
  fi
}

こんな感じのラッパー関数を書いて、新しくインストールするパッケージに dirがあったら古いものを削除する、みたいな事をしていました。 (これだと後でまたstowしようとすると競合が起こるので、いっそ

rm -f $1/share/info/dir

とパッケージ内の物を消してしまっても良いかもしれません、 まずdirの情報なんて使わない、というのであれば。)

以前手動でやってた時も良くこの問題が起きて 取り敢えず手で消して、みたいなことをしていました。

追記: 2015/04/22

コメントを貰いましたが、stowには--ignore=REGREPオプションを使って 特定をファイルを無視する事が出来ます。

このREGREPはperlな正規表現を使って指定します。

上の問題のファイルだけを無視したいなら

stow --ignore='share/info/dir' <package>

の様な形。

さらにstowには--defer--overrideというオプションもあって、 れらは他のパッケージの中に指定したファイルがある場合に限り それぞれ、無視、または上書きします2

もし複数のファイルやディレクトリを指定したい場合には、 --ignore=name1 --ignore=name2みたいにそれぞれ指定してもよいし、 perlな正規表現を使って--ignore='name1|name2'みたいにも出来ます。

上のいちいち消してる作業は--overrideと全く同じなのでこれで そのまま代替出来ます。

下にXStowについて書きましたが、Stowの方はGNUパッケージで よりいろんな所で配布されていてapt-getとかでも取りやすいですし、 XStowはC++で書かれているので、ソースからコンパイルして入れる必要がある時、 g++とか入って無いといれなきゃいけなかったり Stowよりはちょっt入れるのに大変かもしれません。

真面目にshare/info/dirの情報をマージしたい場合には XStowを使うと便利ですが、 そうでない場合はStowで --override='share/info/dir'オプション付きで行うのが 良いです。

-Dで削除する際にこのオプションがあっても無くても 悪さはしないので

alias stow="stow --override='share/info/dir'"

みたいにstow自体でエイリアスでオプションを与えてしまっても良いかもしれません。

追記ここまで

XStow

XStow はC++で書かれたStowの拡張版です。(StowはPerl。)

一応ページを見るとIt supports all features of Stow with some extensions. と書いてあります。

ただ、これ、長い間開発が止まっていて、2010年から暫く更新がありませんでした。

上のdirの問題が起きた時なんかもこれを見つけたりしましたが、 どうも古いので使わないほうが良さそうだ、ということでStowの方を使ってました。

readline - Dealing with GNU Stow conflicts - Unix & Linux Stack Exchange

この問題はStowのToDoリスト には入れてある様です。

で、古いままだと思ってたら、昨年また更新されたようです。 Stowの方は2012年がリリース版の最終更新なので (GitHubのページ を見ると最近もちょこちょこ更新はしている様ですが) XStowのが新しいとうことになります。

ということで、使っても良いだろうとで使ってみることに。

ローカルインストールということで、

http://downloads.sourceforge.net/xstow/xstow-1.0.2.tar.bz2

からダウンロードしてインストールします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
p=xstow
wget --no-check-certificate http://downloads.sourceforge.net/xstow/xstow-1.0.2.tar.bz2
tar jxf xstow-1.0.2.tar.bz2
v=`ls -d $p-*|grep -v 'tar.bz2'`
cd $v
CFLAGS="-L$HOME/usr/local/lib -I$HOME/usr/local/include" \
  CPPFLAGS="-L$HOME/usr/local/lib -I$HOME/usr/local/include" \
  LDFLAGS="-L$HOME/usr/local/lib" \
  ./configure --prefix=/$HOME/usr/local/stow/$v
make
make install
cd $HOME/usr/local/stow
$v/bin/xstow $v
rm -rf ~/tmp/${v%%-*}*

取り敢えずインストールするディレクトリは~/usr/local/stowで。

後は、

$ xstow <package>

でインストール、

$ xstow -D <package>

でアンインストール、はStowと一緒です。

で、このままだとStowと同じ様に競合で失敗しますが、これを避けるには2つあって、 1つは

$ xstow -f <package>

とすることで、競合するファイルを無視することが出来ます。

もう一つは、上のStackExchangeにある方法で、 XStowの設定ファイル、xstow.iniに以下のような設定を書いておくことです。

[exec]
match = dir # GNU info index file
exec = merge-info %t %s -o %t
exec-unstow = merge-info -u %t %s -o %t

xstow.iniはホームディレクトリかstowでパッケージをインストールする ディレクトリに置いておきます。 (ホームディレクトリの場合は.xstow.iniと隠しファイルにしてもOK。)

xstow.ini

設定ではdirというファイルがあった時、これを merge-infoというコマンドでマージするようにする、と言うもの。 このmerge-infoもXStowの中に入っています。(xstowと一緒にインストールされる。)

マージしようと思うとちょっと面倒なので、 取り敢えず今のところdirは要らないかな、ということで -fを使って回避するようにします。

前回のスクリプトをアップデートしたのがこちら。

linux_install.sh

Sponsored Links
Sponsored Links

« Anker Astro E1モバイルバッテリーがまた値下げしてる。。。 日本語Markdownからスライド資料を作る »