コンテンツにスキップ

カスタムアダプター

特殊なユースケースでは、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では自動設定)
gitBinarygit実行ファイル名(デフォルト: 'git'
env追加の環境変数
pathPrefixPATHの先頭に追加するディレクトリ
homeカスタムHOMEディレクトリ(WindowsではUSERPROFILEも設定)
credential資格情報ヘルパーの設定