Let's start Scheme

2018-03-02

ファイルタイムスタンプとChicken Scheme

Sagittariusではファイルのタイムスタンプを変更する方法を用意していなかった。それが問題になったことがなかったというのが一番の理由である。が、先日これが問題になったので追加したという話。

問題になったもの
Scheme EnvでChickenのインストーラを作成していたら(archive)で展開したファイル郡をビルドできなかった。もちろんtarで展開してやれば動く。エラーとしては、Chickenが事前ビルドプロセスで生成しているファイルをビルドしようとしているというものだった。(例:library.scmからlibrary.cを生成する) これらは依存関係としてMakefileに記載されている。

原因
(当たり前のことで書くのも憚られるが)Makefileの依存関係の解決はファイルの更新日時に強く影響される。上記の場合だと、library.scmはlibrary.cよりも後に変更が加えられているのでmakeが変更有りとして解決しようとしたというもの。(.scmはアルファベット順で.cより後に来るから、展開順的にそうなった)

解決
change-file-timestamps!という手続きを追加し、(archive)で展開されたファイルのタイムスタンプを変更するようにした。特に何にひねりもない王道とも言える。

どうでもいい捕捉
新たに追加された手続きchange-file-timestamps!はこんな感じで使う。
(change-file-timestamps! file 1 (make-time time-utc 0 0))
fileは文字列で存在するファイル名を指す必要がある。残りの引数はそれぞれ、atimemtimeに相当し、最終アクセス日時と最終更新日を変更する。上記の場合だと、最終アクセス日時が現在時間+1秒になり、最終更新日がUnix時間の開始日(1970年1月1日 0時0分0秒 GMT)になる。更新をしたくない場合は#fを指定し、現在時にしたい場合は#t(時間オブジェクトまたは実数以外の真値)を与える。

これが入ったことで、今まで無理やり実装するしかなかったtouchが簡単にできるようになる。例えばこんな感じ。
(import (rnrs) (sagittarius))

(define (touch file)
  (if (file-exists? file)
      (change-file-timestamps! file #t #t)
      (call-with-output-file file (lambda (out)))))

(touch "foo")
上記はあると便利かもしれないが、今のところ用途がないので、どこのライブラリにも入れてない。要望があれば入れる感じ。

No comments:

Post a Comment