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
のドキュメントを見ると一見かなりシンプルに見えるが、実は TarOptions
は TarInfo
を継承していて、メタデータを細かく指定できる。ざっとソースコードを見た感じだと、上記のコード例で指定しているメタデータを固定値で埋めれば、ファイルの中身とサイズ以外のメタデータに依存することなくアーカイブを作成してくれる。
GNU tar の生成するアーカイブとはもちろん一致しないが、Deno が動く環境であれば OS によらず同じハッシュ値のアーカイブが出力されるはずで、そういう意味では同じバージョンの Deno とライブラリを用意できれば再現性はある。
GNU tar を使っていたときのコードと比べると、環境依存のコードや複雑なオプション指定が無くなってスッキリした。