zerogit
Pure Rust製の軽量Gitクライアントライブラリ。最小限の依存でGitリポジトリの読み書きを実現します。
特徴
- Pure Rust: Cバインディングなし、クロスコンパイルが容易
- 最小依存:
miniz_oxide(zlib解凍)のみに依存 - 軽量: 必要な機能だけを実装したシンプルな設計
- 学習向け: Git内部構造の理解に役立つクリーンな実装
インストール
Cargo.toml に以下を追加:
[]
= "0.2"
必要環境
- Rust 1.70.0 以上
- Linux / macOS / Windows
クイックスタート
リポジトリを開いてログを表示
use ;
ステータスを確認
use ;
特定コミットの詳細を取得
use ;
ブランチ一覧
use ;
API概要
主要な型
| 型 | 説明 |
|---|---|
Repository |
リポジトリ操作のエントリーポイント |
Commit |
コミット情報(author, message, parents等) |
Tree |
ディレクトリ構造 |
Blob |
ファイル内容 |
Oid |
オブジェクトID(SHA-1ハッシュ) |
Branch |
ブランチ情報 |
Head |
HEAD参照(ブランチまたはdetached) |
Repository メソッド
// リポジトリを開く
open?; // 指定パス
discover?; // 親ディレクトリを探索
// 読み取り操作
repo.head?; // HEAD取得
repo.branches?; // ブランチ一覧
repo.log?; // コミット履歴(Iterator)
repo.status?; // ワーキングツリー状態
repo.commit?; // コミット取得
repo.tree?; // ツリー取得
repo.blob?; // Blob取得
repo.index?; // インデックス取得
// 書き込み操作
repo.add?; // ファイルをステージ
repo.add_all?; // 全変更をステージ
repo.reset?; // ステージを解除
repo.create_commit?; // コミット作成
repo.create_branch?; // ブランチ作成
repo.delete_branch?; // ブランチ削除
repo.checkout?; // ブランチ切り替え
詳細は APIドキュメント を参照してください。
使用例
ファイル内容の取得
let repo = discover?;
let head = repo.head?;
let commit = repo.commit?;
let tree = repo.tree?;
if let Some = tree.get
コミット間の差分ファイル一覧
let repo = discover?;
let commits: = repo.log?.take.?;
if commits.len == 2
ファイルをステージしてコミット
use ;
ブランチ操作
use ;
ロードマップ
Phase 1: 読み取り操作(MVP)✅
ローカルリポジトリの読み取り機能を提供します。
- オブジェクト読み取り(blob/tree/commit)
- 参照解決(HEAD/branches/tags)
- コミット履歴イテレータ
- ワーキングツリーステータス
- インデックス読み取り
Phase 2: 書き込み操作
ローカルリポジトリへの書き込み機能を提供します。
-
add/reset- ステージング操作 -
commit- コミット作成 -
branch- ブランチ作成・削除 -
checkout- ブランチ切り替え
Phase 3: 差分・マージ・Packfile
差分計算とPackfile対応を提供します。
| 機能 | 説明 | 難易度 |
|---|---|---|
| Tree diff | 2つのTree間の差分計算 | 中 |
| Blob diff | ファイル内容の行単位差分(Myers算法) | 高 |
| Packfile読み取り | .git/objects/pack/*.pack の読み取り |
高 |
| Packfileインデックス | .idx ファイルによる高速検索 |
中 |
| Delta復元 | ofs_delta / ref_delta の展開 | 高 |
| 3-way merge | 共通祖先ベースのマージ | 高 |
想定API:
// 差分取得
let diff = repo.diff_trees?;
for delta in diff.deltas
// Packfile対応(内部的に自動処理)
let obj = repo.object?; // looseまたはpackから透過的に取得
Phase 4: リモート操作(別crate: zerogit-remote)
ネットワーク操作は依存関係が増えるため、別crateとして提供予定です。
なぜ別crateなのか?
| 観点 | zerogit (コア) | zerogit-remote |
|---|---|---|
| 依存 | miniz_oxide のみ |
rustls, russh, ureq 等 |
| ビルド時間 | 高速 | TLS/SSH依存で増加 |
| WASM対応 | ○ | △(制限あり) |
| 組み込み用途 | ○ | △ |
サポート予定プロトコル
| プロトコル | URL形式 | 認証方式 | 優先度 |
|---|---|---|---|
| HTTPS | https://github.com/... |
Basic / Bearer Token | 高 |
| SSH | git@github.com:... |
SSH鍵 | 中 |
| Git | git://... |
なし(読み取り専用) | 低 |
想定API
use Repository;
use ;
// クローン
let repo = clone?;
// フェッチ
let remote = repo.remote?;
remote.fetch?;
// プッシュ
remote.push?;
技術的な実装要素
Smart HTTP Protocol:
┌─────────┐ ┌─────────┐
│ Client │ GET /info/refs │ Server │
│ │ ───────────────────────────> │ │
│ │ 200 OK (refs + capabilities)│ │
│ │ <─────────────────────────── │ │
│ │ │ │
│ │ POST /git-upload-pack │ │
│ │ (want/have negotiation) │ │
│ │ ───────────────────────────> │ │
│ │ 200 OK (packfile) │ │
│ │ <─────────────────────────── │ │
└─────────┘ └─────────┘
代替アプローチ
リモート操作が必要だが zerogit-remote を待てない場合、システムのgitコマンドと連携できます:
use Command;
将来の検討事項
- Worktree対応: 複数のワーキングツリー
- Submodule対応: サブモジュールの読み取り
- Sparse checkout: 部分的なチェックアウト
- Shallow clone: 履歴を限定したクローン
貢献
コントリビューションを歓迎します!
開発環境のセットアップ
# テスト用フィクスチャの準備
# テスト実行
# フォーマットとLint
プルリクエスト
- Issueを作成して変更内容を議論
- フォークしてfeatureブランチを作成
- 変更を実装(テスト必須)
cargo fmtとcargo clippyを実行- プルリクエストを送信
コーディング規約
cargo fmtでフォーマットcargo clippyの警告をゼロに- 公開APIには必ずドキュメントコメント
- 新機能にはテストを追加
設計ドキュメント
詳細な設計については以下を参照:
関連プロジェクト
zerogitは学習目的と軽量な用途に特化しています。フル機能が必要な場合は上記のプロジェクトを検討してください。
ライセンス
本プロジェクトはデュアルライセンスです:
お好きな方を選択してください。
謝辞
- Git - オリジナル実装とドキュメント
- Pro Git Book - Git内部構造の解説
- gitoxide - Pure Rust実装の参考