カスタムアダプター
特殊なユースケースでは、type-gitがgitコマンドを実行する方法やファイル操作を処理する方法を制御するカスタムアダプターを作成できます。
カスタムアダプターを作成する場面
- モックgitコマンドでのテスト
- カスタムプロセス起動(コンテナ、SSH)
- カスタムファイルシステム(仮想FS、クラウドストレージ)
- 全gitオペレーションのログ/監査
ExecAdapterインターフェース
interface ExecAdapter { getCapabilities(): Capabilities; spawn(options: SpawnOptions, handlers?: StreamHandler): Promise<SpawnResult>; spawnStreaming?(options: SpawnOptions): SpawnHandle;}
type SpawnOptions = { argv: string[]; env?: Record<string, string>; cwd?: string; signal?: AbortSignal;};
type SpawnResult = { stdout: string; stderr: string; exitCode: number; aborted: boolean;};FsAdapterインターフェース
interface FsAdapter { createTempFile(prefix?: string): Promise<string>; deleteFile(filePath: string): Promise<void>; deleteDirectory(dirPath: string): Promise<void>; exists(filePath: string): Promise<boolean>; tail(options: TailOptions): Promise<void>; tailStreaming?(filePath: string, options?: TailStreamingOptions): TailHandle;}例: ロギングアダプター
import { createGit, createNodeAdapters } from 'type-git/node';import type { ExecAdapter, SpawnOptions, SpawnResult } from 'type-git';
class LoggingExecAdapter implements ExecAdapter { private inner: ExecAdapter;
constructor(inner: ExecAdapter) { this.inner = inner; }
getCapabilities() { return this.inner.getCapabilities(); }
async spawn(options: SpawnOptions, handlers?: StreamHandler): Promise<SpawnResult> { console.log('[GIT]', options.argv.join(' ')); const start = Date.now();
const result = await this.inner.spawn(options, handlers);
console.log(`[GIT] ${Date.now() - start}msで完了 (exit: ${result.exitCode})`); return result; }}
// 使用方法const nodeAdapters = createNodeAdapters();const git = createGit({ adapters: { exec: new LoggingExecAdapter(nodeAdapters.exec), fs: nodeAdapters.fs, },});例: テスト用モックアダプター
class MockExecAdapter implements ExecAdapter { private responses: Map<string, SpawnResult> = new Map();
getCapabilities() { return { runtime: 'node' as const }; }
mockCommand(pattern: string, result: Partial<SpawnResult>) { this.responses.set(pattern, { stdout: result.stdout ?? '', stderr: result.stderr ?? '', exitCode: result.exitCode ?? 0, aborted: false, }); }
async spawn(options: SpawnOptions): Promise<SpawnResult> { const command = options.argv.join(' ');
for (const [pattern, result] of this.responses) { if (command.includes(pattern)) { return result; } }
throw new Error(`モックされていないコマンド: ${command}`); }}
// テストでの使用const mockExec = new MockExecAdapter();mockExec.mockCommand('--version', { stdout: 'git version 2.40.0' });mockExec.mockCommand('status --porcelain', { stdout: '' });
const git = createGit({ adapters: { exec: mockExec, fs: createMockFsAdapter(), },});環境分離
type-gitは以下のようなシナリオで環境分離をサポートしています:
- git設定を分離するためのカスタムHOMEディレクトリの使用
- カスタムパスにある特定バージョンのgitの使用
- 資格情報ヘルパーの設定
- カスタム環境変数でのgit実行
TypeGitオプション
TypeGitクラスはcreateGitと同じオプション(adaptersを除く)を受け付けます:
import { TypeGit } from 'type-git/node';
// git設定を分離するためにHOMEを変更const git = new TypeGit({ home: '/isolated/home',});
// グローバル設定操作は /isolated/home/.gitconfig を使用await git.config.set('user.name', 'Test User');await git.config.set('user.email', 'test@example.com');
// 分離された設定を使用してクローンconst repo = await git.clone('https://github.com/user/repo.git', './repo');カスタムGitバイナリパス
pathPrefixを設定して特定バージョンのgitを使用:
const git = new TypeGit({ pathPrefix: ['/opt/git-2.45/bin'], // PATHの先頭に追加});
const version = await git.version(); // /opt/git-2.45/bin/git を使用資格情報ヘルパーの設定
認証用の資格情報ヘルパーを設定:
const git = new TypeGit({ credential: { helper: 'store', // git-credential-store を使用 },});
// またはカスタムヘルパーパスでconst git = new TypeGit({ credential: { helper: 'my-helper', helperPath: '/path/to/git-credential-my-helper', },});組み合わせた例
import { TypeGit } from 'type-git/node';
// 完全に分離されたgit環境const git = new TypeGit({ home: '/app/git-home', // 分離された .gitconfig pathPrefix: ['/app/git/bin'], // カスタムgitバイナリ env: { GIT_AUTHOR_NAME: 'CI Bot', GIT_AUTHOR_EMAIL: 'ci@example.com', }, credential: { helper: 'store', },});
// すべての操作が分離された環境を使用await git.config.set('user.name', 'CI Bot');const repo = await git.clone('https://github.com/user/repo.git', './repo');createGitの使用
完全な制御(カスタムアダプターを含む)が必要な場合は、TypeGitの代わりにcreateGitを使用:
import { createGit, createNodeAdapters } from 'type-git/node';
const git = createGit({ adapters: createNodeAdapters(), gitBinary: '/custom/path/to/git', env: { GIT_AUTHOR_NAME: 'Custom Author' },});利用可能なオプション
| オプション | 説明 |
|---|---|
adapters | ランタイムアダプター(createGitでは必須、TypeGitでは自動設定) |
gitBinary | git実行ファイル名(デフォルト: 'git') |
env | 追加の環境変数 |
pathPrefix | PATHの先頭に追加するディレクトリ |
home | カスタムHOMEディレクトリ(WindowsではUSERPROFILEも設定) |
credential | 資格情報ヘルパーの設定 |