From f726f24285b9dc7a97ee6eaba6dc3d9cf50824b1 Mon Sep 17 00:00:00 2001 From: JUNYAN <161484815+liyimil@users.noreply.github.com> Date: Sat, 18 Jul 2026 10:29:18 +0800 Subject: [PATCH] feat: support built-in log formats --- .changeset/bright-logs-wave.md | 5 ++ simple-git/src/lib/tasks/log.ts | 87 ++++++++++++++++++++++++++---- simple-git/test/unit/log.spec.ts | 23 ++++++++ simple-git/typings/simple-git.d.ts | 4 ++ simple-git/typings/types.d.ts | 7 ++- 5 files changed, 116 insertions(+), 10 deletions(-) create mode 100644 .changeset/bright-logs-wave.md diff --git a/.changeset/bright-logs-wave.md b/.changeset/bright-logs-wave.md new file mode 100644 index 00000000..2f6950c3 --- /dev/null +++ b/.changeset/bright-logs-wave.md @@ -0,0 +1,5 @@ +--- +'simple-git': minor +--- + +Support Git's oneline, short, medium, full, and fuller log format presets. diff --git a/simple-git/src/lib/tasks/log.ts b/simple-git/src/lib/tasks/log.ts index 568d9d83..578fd0ac 100644 --- a/simple-git/src/lib/tasks/log.ts +++ b/simple-git/src/lib/tasks/log.ts @@ -48,6 +48,72 @@ export interface DefaultLogFields { author_email: string; } +export type BuiltInLogFormat = 'oneline' | 'short' | 'medium' | 'full' | 'fuller'; + +export interface OnelineLogFields { + hash: string; + message: string; +} + +export interface ShortLogFields extends OnelineLogFields { + author_name: string; + author_email: string; +} + +export interface MediumLogFields extends ShortLogFields { + author_date: string; +} + +export interface FullLogFields extends ShortLogFields { + committer_name: string; + committer_email: string; +} + +export interface FullerLogFields extends FullLogFields { + author_date: string; + commit_date: string; +} + +export type BuiltInLogFields = T extends 'oneline' + ? OnelineLogFields + : T extends 'short' + ? ShortLogFields + : T extends 'medium' + ? MediumLogFields + : T extends 'full' + ? FullLogFields + : FullerLogFields; + +const builtInLogFormats: Record> = { + oneline: { hash: '%H', message: '%s' }, + short: { hash: '%H', author_name: '%aN', author_email: '%aE', message: '%s' }, + medium: { + hash: '%H', + author_name: '%aN', + author_email: '%aE', + author_date: '%aD', + message: '%B', + }, + full: { + hash: '%H', + author_name: '%aN', + author_email: '%aE', + committer_name: '%cN', + committer_email: '%cE', + message: '%B', + }, + fuller: { + hash: '%H', + author_name: '%aN', + author_email: '%aE', + author_date: '%aD', + committer_name: '%cN', + committer_email: '%cE', + commit_date: '%cD', + message: '%B', + }, +}; + export type LogOptions = { file?: string; format?: T; @@ -96,17 +162,20 @@ export function parseLogOptions( customArgs: string[] = [] ): ParsedLogOptions { const splitter = filterType(opt.splitter, filterString, SPLITTER); + const formatName = filterType(opt.format, filterString) as BuiltInLogFormat | undefined; const format = filterPlainObject(opt.format) ? opt.format - : { - hash: '%H', - date: opt.strictDate === false ? '%ai' : '%aI', - message: '%s', - refs: '%D', - body: opt.multiLine ? '%B' : '%b', - author_name: opt.mailMap !== false ? '%aN' : '%an', - author_email: opt.mailMap !== false ? '%aE' : '%ae', - }; + : formatName && builtInLogFormats[formatName] + ? builtInLogFormats[formatName] + : { + hash: '%H', + date: opt.strictDate === false ? '%ai' : '%aI', + message: '%s', + refs: '%D', + body: opt.multiLine ? '%B' : '%b', + author_name: opt.mailMap !== false ? '%aN' : '%an', + author_email: opt.mailMap !== false ? '%aE' : '%ae', + }; const [fields, formatStr] = prettyFormat(format, splitter); diff --git a/simple-git/test/unit/log.spec.ts b/simple-git/test/unit/log.spec.ts index 43298660..1091a3fe 100644 --- a/simple-git/test/unit/log.spec.ts +++ b/simple-git/test/unit/log.spec.ts @@ -265,6 +265,29 @@ ${START_BOUNDARY}blah ]); }); + it('allows for built-in fuller format', async () => { + const task = git.log({ format: 'fuller', splitter: '||' }); + await closeWithSuccess(` +${START_BOUNDARY}aaf7f71d53fdbe5f1783f4cc34514cb1067b9131||Steve King||steve@mydev.co||Tue, 9 Jul 2019 11:33:17 +0100||Jill King||jill@mydev.co||Wed, 10 Jul 2019 09:00:00 +0100||hello +world${COMMIT_BOUNDARY} + `); + + assertExecutedCommands( + 'log', + `--pretty=format:${START_BOUNDARY}%H||%aN||%aE||%aD||%cN||%cE||%cD||%B${COMMIT_BOUNDARY}` + ); + expect((await task).latest).toEqual({ + hash: 'aaf7f71d53fdbe5f1783f4cc34514cb1067b9131', + author_name: 'Steve King', + author_email: 'steve@mydev.co', + author_date: 'Tue, 9 Jul 2019 11:33:17 +0100', + committer_name: 'Jill King', + committer_email: 'jill@mydev.co', + commit_date: 'Wed, 10 Jul 2019 09:00:00 +0100', + message: 'hello\nworld', + }); + }); + it('picks out the latest item', async () => { const task = git.log(); await closeWithSuccess(` diff --git a/simple-git/typings/simple-git.d.ts b/simple-git/typings/simple-git.d.ts index 0afac60a..c1aaa9e9 100644 --- a/simple-git/typings/simple-git.d.ts +++ b/simple-git/typings/simple-git.d.ts @@ -652,6 +652,10 @@ export interface SimpleGit extends SimpleGitBase { * * @see https://git-scm.com/docs/git-log */ + log( + options: types.LogOptions & { format: T }, + callback?: types.SimpleGitTaskCallback>> + ): Response>>; log( options?: types.TaskOptions | types.LogOptions, callback?: types.SimpleGitTaskCallback> diff --git a/simple-git/typings/types.d.ts b/simple-git/typings/types.d.ts index d079d619..005d8a15 100644 --- a/simple-git/typings/types.d.ts +++ b/simple-git/typings/types.d.ts @@ -1,5 +1,10 @@ export type { RemoteWithoutRefs, RemoteWithRefs } from '../src/lib/responses/GetRemoteSummary'; -export type { LogOptions, DefaultLogFields } from '../src/lib/tasks/log'; +export type { + BuiltInLogFields, + BuiltInLogFormat, + DefaultLogFields, + LogOptions, +} from '../src/lib/tasks/log'; export type { outputHandler,