log.ts•3.08 kB
/**
* @fileoverview CLI provider git log operation
* @module services/git/providers/cli/operations/commits/log
*/
import type { RequestContext } from '@/utils/index.js';
import type {
GitLogOptions,
GitLogResult,
GitOperationContext,
} from '../../../../types.js';
import {
buildGitCommand,
GIT_FIELD_DELIMITER,
GIT_RECORD_DELIMITER,
mapGitError,
} from '../../utils/index.js';
/**
* Execute git log to view commit history.
*
* @param options - Log options
* @param context - Operation context
* @param execGit - Function to execute git commands
* @returns Log result
*/
export async function executeLog(
options: GitLogOptions,
context: GitOperationContext,
execGit: (
args: string[],
cwd: string,
ctx: RequestContext,
) => Promise<{ stdout: string; stderr: string }>,
): Promise<GitLogResult> {
try {
// Format: hash, shortHash, author, authorEmail, timestamp, subject, body, parents
const args = [
`--format=%H${GIT_FIELD_DELIMITER}%h${GIT_FIELD_DELIMITER}%an${GIT_FIELD_DELIMITER}%ae${GIT_FIELD_DELIMITER}%at${GIT_FIELD_DELIMITER}%s${GIT_FIELD_DELIMITER}%b${GIT_FIELD_DELIMITER}%P${GIT_RECORD_DELIMITER}`,
];
if (options.maxCount) {
args.push(`-n${options.maxCount}`);
}
if (options.since) {
args.push(`--since=${options.since}`);
}
if (options.until) {
args.push(`--until=${options.until}`);
}
if (options.author) {
args.push(`--author=${options.author}`);
}
if (options.grep) {
args.push(`--grep=${options.grep}`);
}
// Add branch argument if specified (must come before -- separator)
if (options.branch) {
args.push(options.branch);
}
// Add file path filter if specified (must come after -- separator)
if (options.path) {
args.push('--', options.path);
}
const cmd = buildGitCommand({ command: 'log', args });
const gitOutput = await execGit(
cmd,
context.workingDirectory,
context.requestContext,
);
const commits = gitOutput.stdout
.split(GIT_RECORD_DELIMITER)
.filter((r) => r.trim())
.map((record) => {
const fields = record.trim().split(GIT_FIELD_DELIMITER);
const commit: {
hash: string;
shortHash: string;
author: string;
authorEmail: string;
timestamp: number;
subject: string;
body?: string;
parents: string[];
refs?: string[];
} = {
hash: fields[0] || '',
shortHash: fields[1] || '',
author: fields[2] || '',
authorEmail: fields[3] || '',
timestamp: parseInt(fields[4] || '0', 10),
subject: fields[5] || '',
parents: (fields[7] || '').split(' ').filter((p) => p),
};
if (fields[6]) {
commit.body = fields[6];
}
return commit;
});
const result = {
commits,
totalCount: commits.length,
};
return result;
} catch (error) {
throw mapGitError(error, 'log');
}
}