monolithic kernel

Deno の標準ライブラリで再現性のある tar アーカイブ作成

先日記事を書いたときは GNU tar を使っていたのだが、その後 Deno の標準ライブラリの @std/archive を使うことで tar 形式を扱えると知った。見てみたところ、こちらでも再現性のある形でアーカイブを作成することが可能で、かつインストールされている GNU tar に依存しないので、Deno を使う前提なら便利。

import * as archive from "jsr:@std/archive@^0.221.0";
import * as io from "jsr:@std/io@^0.221.0";

const mtime = new Date(...);
const output = "/path/to/output";
const dir = "/path/to/dir";
const files = [
  "file1",
  "file2",
];
files.sort();

const tar = new archive.Tar();
for (const file of files) {
  await tar.append(file, {
    filePath: path.join(dir, file),
    fileMode: 0o644,
    mtime: mtime.getDate() / 1000,
    uid: 0,
    gid: 0,
  });
}
const writer = await Deno.open(output, { write: true, create: true });
try {
  await io.copy(tar.getReader(), writer);
} finally {
  writer.close();
}

Tar#append で指定する TarOptions のドキュメントを見ると一見かなりシンプルに見えるが、実は TarOptionsTarInfo を継承していて、メタデータを細かく指定できる。ざっとソースコードを見た感じだと、上記のコード例で指定しているメタデータを固定値で埋めれば、ファイルの中身とサイズ以外のメタデータに依存することなくアーカイブを作成してくれる。

GNU tar の生成するアーカイブとはもちろん一致しないが、Deno が動く環境であれば OS によらず同じハッシュ値のアーカイブが出力されるはずで、そういう意味では同じバージョンの Deno とライブラリを用意できれば再現性はある。

GNU tar を使っていたときのコードと比べると、環境依存のコードや複雑なオプション指定が無くなってスッキリした。


Related articles