0時に寝て3時に起きて5時に起きて6時半に起きた。

jar ファイルと git のリビジョン

java パッケージのフォーマットとして jar ファイルがある。開発中の jar ファイルは snapshot という特別なバージョンで管理したりするが、この snapshot と git のリビジョンが対応していないので snapshot jar だけではどのリビジョンのソースからビルドされたかがわからない。jar には JAR File Specification で定義された META-INF/MANIFEST.MF に任意のメタデータを保持できる。maven なら maven git commit id pluginApache Maven JAR Plugin を組み合わせれば、ビルド設定だけで git のリポジトリ情報を任意のメタデータとして jar に含めることができる。試しにプラグインの検証も兼ねてやってみた。例えば、次のようなマニフェストを作れる。

Manifest-Version: 1.0
Created-By: Apache Maven 3.6.3
Built-By: t2y
Build-Jdk: 11.0.13
Specification-Title: My Nice Product
Specification-Version: 1.0
Artifact-Id: my-product
Build-Time: 2022-02-21T11:39:07Z
Git-Branch: main
Git-Commit-Id: 81a4642
Git-Commit-Time: 2022-02-21T19:39:30+0900
Git-Commit-User: Tetsuya Morimoto

java のコードからマニフェストを取得するサンプルコードはこんな感じ。ググるといくつかやり方があるようなので他の実装もある。但し、このコードだと複数の jar のマニフェストを取得してしまうので、あとで自分がみたい jar のマニフェストをフィルターする処理が必要になる。

private static final String MANIFEST_PATH = "META-INF/MANIFEST.MF";

public static Map<String, Manifest> getManifests() throws IOException, URISyntaxException {
    var map = new HashMap<String, Manifest>();
    var resources = MyUtil.class.getClassLoader().getResources(MANIFEST_PATH);
    while (resources.hasMoreElements()) {
        var elem = resources.nextElement();
        var part = elem.toURI().getSchemeSpecificPart();
        if (part != null) {
            try (var stream = elem.openStream()) {
                map.put(part, new Manifest(stream));
            }
        }
    }
    return map;
}