開発作業中にローカルの git レポジトリ内の古いファイルを参照したいことがあります。
過去のブランチに git switch
するのは少し面倒だし、間違えて作業中のファイルを失うことも。
そこで、任意リビジョンの任意ファイルを参照できる Node.js のライブラリや Web サーバを書いてみました。
- https://www.npmjs.com/package/git-cat-file (1) JSライブラリ
- https://www.npmjs.com/package/serve-static-git (2) Expressミドルウェア
- https://www.npmjs.com/package/weboverlay (3) CLI Webサーバ
weboverlay を使えばサーバ1つで、任意のブランチ・コミットにアクセスできるので、たとえば、ブラウザの2つのタブで master ブランチと develop ブランチのウェブサイトを同時に開いて比較することもできます。
(1) JS ライブラリ git-cat-file
標準 git
コマンドの git cat-file -p
等の機能をピュア JavaScript (TypeScript) で実装したのが git-cat-file になります。
① .git
ディレクトリのパス
② ブランチ名やコミットID
③ ファイルのパス
の3点を指定すると、そのファイルのバイナリデータを Buffer で取り出せます。
const {openLocalRepo} = require("git-cat-file");
async function catFile(revision, path) {
const repo = openLocalRepo("path/to/repository/.git");
const commit = await repo.getCommit(revision);
const file = await commit.getFile(path);
process.stdout.write(file.data);
}
catFile("HEAD", "path/to/file.txt");
git レポジトリの形式としては、非圧縮の loose と git gc
で圧縮された packed 形式の両方に対応しています。
(2) Express ミドルウェア serve-static-git
Express.js で静的ファイルを公開するときの app.use(express.static("htdocs"))
のミドルウェアの実装 serve-static と同様に、git レポジトリ内に格納された静的ファイルを提供する Express ミドルウェアが serve-static-git になります。
ローカルファイルシステム上の静的ファイルを提供するとき:
const express = require("express");
const app = express();
app.use(express.static("htdocs"));
app.listen(3000);
git レポジトリ内から静的ファイルを提供するとき:
const express = require("express");
const {serveStaticGit} = require("serve-static-git");
const app = express();
app.use(serveStaticGit({
repo: "path/to/repository/.git",
root: "htdocs",
}));
app.listen(3000);
raw.githubusercontent.com ではパスでリビジョン(git ブランチ名やコミット ID)を指定するのに対して、
serve-static-git ではリクエストヘッダ Host:
の冒頭(サブドメイン名・ホスト名)でリビジョンを指定するため、
絶対パスで記述しているリンクも参照できます。
いまの Chrome 等のモダンブラウザでは xxxx.localhost
形式で任意のホスト名を指定できます。
(例1) main レポジトリ内の htdocs/index.html ファイルを取り出すとき
→ http://main.localhost:3000/index.html
(例2) develop レポジトリ内の htdocs/css/style.css ファイルを取り出すとき
→ http://develop.localhost:3000/css/style.css
ただし、hotfix/xxx
・feature/xxx
・release/xxx
のような記号の入るブランチやタグは、リクエストのホスト名に指定できないため代わりにコミット ID で指定するか、または 210.refs.ts を参考にして refs オプションでリビジョンを指定する定義を指定する必要があります。
(例3) curl で明示的にリクエストヘッダ host:
を指定する例:
curl -s -H 'host: feature/xxx' http://localhost:3000/index.html
(例4) リクエストヘッダ x-refs:
で指定する例:(※要・refsオプション)
curl -s -H 'x-refs: feature/xxx' http://localhost:3000/index.html
指定したブランチが存在しなかった場合は、HEAD
にフォールバックします。
なお、提供できるのは静的ファイルのみです。動的な API などは提供できません。
(3) CLI ワンライナー Web サーバ weboverlay
最後に紹介するのは、ワンライナーで Web サーバを構築できる weboverlay になります。
自前で git-cat-file
・serve-static-git
を使うコードを書かずに、CLI でサーバを起動できます。
# インストール
npm install weboverlay
# サーバを起動する
node_modules/.bin/weboverlay --port=3000 path/to/repository/.git:htdocs
# Chrome 等でアクセスする
open http://main.localhost:3000/index.html
# curl でアクセスする
curl -s -H 'Host: main' http://localhost:3000/index.html