Skip to content

Commit

Permalink
Add integration tests for use of log formats in git.log and unit/in…
Browse files Browse the repository at this point in the history
…tegration tests for `git.diffSummary`

`parseStringResponse` allows specifying whether to trim trailing white space on each line, disables on the diff parser

Closes #796
  • Loading branch information
steveukx committed Jun 18, 2022
1 parent 3b2c1b3 commit fd29242
Show file tree
Hide file tree
Showing 15 changed files with 239 additions and 31 deletions.
1 change: 0 additions & 1 deletion simple-git/src/lib/args/log-format.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

export enum LogFormat {
NONE = '',
STAT = '--stat',
Expand Down
2 changes: 1 addition & 1 deletion simple-git/src/lib/errors/git-error.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SimpleGitTask } from '../types';
import type { SimpleGitTask } from '../types';

/**
* The `GitError` is thrown when the underlying `git` process throws a
Expand Down
2 changes: 1 addition & 1 deletion simple-git/src/lib/parsers/parse-branch-delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const parsers: LineParser<BranchMultiDeleteResult>[] = [
];

export const parseBranchDeletions: TaskParser<string, BranchMultiDeleteResult> = (stdOut, stdErr) => {
return parseStringResponse(new BranchDeletionBatch(), parsers, stdOut, stdErr);
return parseStringResponse(new BranchDeletionBatch(), parsers, [stdOut, stdErr]);
}

export function hasBranchDeletionError(data: string, processExitCode: ExitCodes): boolean {
Expand Down
2 changes: 1 addition & 1 deletion simple-git/src/lib/parsers/parse-diff-summary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,5 @@ const diffSummaryParsers: Record<LogFormat, LineParser<DiffResult>[]> = {
export function getDiffParser(format = LogFormat.NONE) {
const parser = diffSummaryParsers[format];

return (stdOut: string) => parseStringResponse(new DiffSummary(), parser, stdOut);
return (stdOut: string) => parseStringResponse(new DiffSummary(), parser, stdOut, false);
}
2 changes: 1 addition & 1 deletion simple-git/src/lib/parsers/parse-fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ export function parseFetchResult (stdOut: string, stdErr: string): FetchResult {
branches: [],
tags: [],
};
return parseStringResponse(result, parsers, stdOut, stdErr);
return parseStringResponse(result, parsers, [stdOut, stdErr]);
}
4 changes: 2 additions & 2 deletions simple-git/src/lib/parsers/parse-pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const errorParsers: LineParser<PullFailedResult>[] = [
];

export const parsePullDetail: TaskParser<string, PullDetail> = (stdOut, stdErr) => {
return parseStringResponse(new PullSummary(), parsers, stdOut, stdErr);
return parseStringResponse(new PullSummary(), parsers, [stdOut, stdErr]);
}

export const parsePullResult: TaskParser<string, PullResult> = (stdOut, stdErr) => {
Expand All @@ -59,7 +59,7 @@ export const parsePullResult: TaskParser<string, PullResult> = (stdOut, stdErr)
}

export function parsePullErrorResult(stdOut: string, stdErr: string) {
const pullError = parseStringResponse(new PullFailedSummary(), errorParsers, stdOut, stdErr);
const pullError = parseStringResponse(new PullFailedSummary(), errorParsers, [stdOut, stdErr]);

return pullError.message && pullError;
}
2 changes: 1 addition & 1 deletion simple-git/src/lib/parsers/parse-push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,5 @@ export const parsePushResult: TaskParser<string, PushResult> = (stdOut, stdErr)
}

export const parsePushDetail: TaskParser<string, PushDetail> = (stdOut, stdErr) => {
return parseStringResponse({pushed: []}, parsers, stdOut, stdErr);
return parseStringResponse({pushed: []}, parsers, [stdOut, stdErr]);
}
12 changes: 8 additions & 4 deletions simple-git/src/lib/tasks/diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { isLogFormat, LogFormat, logFormatFromCommand } from '../args/log-format
import { getDiffParser } from '../parsers/parse-diff-summary';
import { configurationErrorTask, EmptyTask } from './task';

export function diffSummaryTask(customArgs: string[]): StringTask<DiffResult> {
export function diffSummaryTask(customArgs: string[]): StringTask<DiffResult> | EmptyTask {
let logFormat = logFormatFromCommand(customArgs);

const commands = ['diff'];
Expand All @@ -16,17 +16,21 @@ export function diffSummaryTask(customArgs: string[]): StringTask<DiffResult> {

commands.push(...customArgs);

return {
return validateLogFormatConfig(commands) || {
commands,
format: 'utf-8',
parser: getDiffParser(logFormat),
}
};
}

export function validateSummaryOptions(customArgs: unknown[]): EmptyTask | void {
export function validateLogFormatConfig(customArgs: unknown[]): EmptyTask | void {
const flags = customArgs.filter(isLogFormat);

if (flags.length > 1) {
return configurationErrorTask(`Summary flags are mutually exclusive - pick one of ${flags.join(',')}`);
}

if (flags.length && customArgs.includes('-z')) {
return configurationErrorTask(`Summary flag ${flags} parsing is not compatible with null termination option '-z'`);
}
}
10 changes: 5 additions & 5 deletions simple-git/src/lib/tasks/log.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Options, StringTask } from '../types';
import { LogResult, SimpleGit } from '../../../typings';
import type { Options, StringTask } from '../types';
import type { LogResult, SimpleGit } from '../../../typings';
import { logFormatFromCommand } from '../args/log-format';
import {
COMMIT_BOUNDARY,
Expand All @@ -18,7 +18,7 @@ import {
} from '../utils';
import { SimpleGitApi } from '../simple-git-api';
import { configurationErrorTask } from './task';
import { validateSummaryOptions } from './diff';
import { validateLogFormatConfig } from './diff';

enum excludeOptions {
'--pretty',
Expand Down Expand Up @@ -150,8 +150,8 @@ export default function (): Pick<SimpleGit, 'log'> {
const next = trailingFunctionArgument(arguments);
const options = parseLogOptions<T>(trailingOptionsArgument(arguments), filterType(arguments[0], filterArray));
const task = rejectDeprecatedSignatures(...rest) ||
validateSummaryOptions(options.commands) ||
createLogTask(options)
validateLogFormatConfig(options.commands) ||
createLogTask(options);

return this._runTask(task, next);
}
Expand Down
8 changes: 5 additions & 3 deletions simple-git/src/lib/tasks/stash-list.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { LogOptions, LogResult } from '../../../typings';
import { logFormatFromCommand } from '../args/log-format';
import { createListLogSummaryParser } from '../parsers/parse-list-log-summary';
import { StringTask } from '../types';
import type { StringTask } from '../types';
import { validateLogFormatConfig } from './diff';
import { parseLogOptions } from './log';
import type { EmptyTask } from './task';

export function stashListTask(opt: LogOptions = {}, customArgs: string[]): StringTask<LogResult> {
export function stashListTask(opt: LogOptions = {}, customArgs: string[]): EmptyTask | StringTask<LogResult> {
const options = parseLogOptions<any>(opt);
const commands = ['stash', 'list', ...options.commands, ...customArgs];
const parser = createListLogSummaryParser(options.splitter, options.fields, logFormatFromCommand(commands));

return {
return validateLogFormatConfig(commands) || {
commands,
format: 'utf-8',
parser,
Expand Down
2 changes: 1 addition & 1 deletion simple-git/src/lib/tasks/task.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { TaskConfigurationError } from '../errors/task-configuration-error';
import { BufferTask, EmptyTaskParser, SimpleGitTask, StringTask } from '../types';
import type { BufferTask, EmptyTaskParser, SimpleGitTask, StringTask } from '../types';

export const EMPTY_COMMANDS: [] = [];

Expand Down
10 changes: 5 additions & 5 deletions simple-git/src/lib/utils/task-parser.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { TaskParser, TaskResponseFormat } from '../types';
import type { MaybeArray, TaskParser, TaskResponseFormat } from '../types';
import { GitOutputStreams } from './git-output-streams';
import { LineParser } from './line-parser';
import { toLinesWithContent } from './util';
import { asArray, toLinesWithContent } from './util';

export function callTaskParser<INPUT extends TaskResponseFormat, RESPONSE>(parser: TaskParser<INPUT, RESPONSE>, streams: GitOutputStreams<INPUT>) {
return parser(streams.stdOut, streams.stdErr);
}

export function parseStringResponse<T>(result: T, parsers: LineParser<T>[], ...texts: string[]): T {
texts.forEach(text => {
for (let lines = toLinesWithContent(text), i = 0, max = lines.length; i < max; i++) {
export function parseStringResponse<T>(result: T, parsers: LineParser<T>[], texts: MaybeArray<string>, trim = true): T {
asArray(texts).forEach(text => {
for (let lines = toLinesWithContent(text, trim), i = 0, max = lines.length; i < max; i++) {
const line = (offset = 0) => {
if ((i + offset) >= max) {
return;
Expand Down
44 changes: 44 additions & 0 deletions simple-git/test/integration/diff.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {
createTestContext,
like,
newSimpleGit,
setUpFilesAdded,
setUpInit,
SimpleGitTestContext
} from '../__fixtures__';

describe('diff', function () {
const nameWithTrailingSpaces = 'name-with-trailing-spaces ';
const fileContent = Array(10).fill('Some content on this line\n').join('');
const nextContent = Array(5).fill('Some content on this line\nDifferent on this line\n').join('');

let context: SimpleGitTestContext;

beforeEach(async () => {
context = await createTestContext();
await setUpInit(context);
await setUpFilesAdded(context, [nameWithTrailingSpaces], '.', fileContent);
await context.file(nameWithTrailingSpaces, nextContent);
});

it('detects diff with --numstat', async () => {
const diff = await newSimpleGit(context.root).diffSummary(['--numstat']);

expect(diff).toEqual(like({
changed: 1,
deletions: 1,
insertions: 10,
files: [
{
file: nameWithTrailingSpaces,
changes: 11,
insertions: 10,
deletions: 1,
binary: false,
}
]
}));
});


});
64 changes: 60 additions & 4 deletions simple-git/test/integration/log.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { promiseResult } from '@kwsites/promise-result';
import {
createTestContext,
GIT_USER_EMAIL,
Expand All @@ -8,6 +9,7 @@ import {
setUpInit,
SimpleGitTestContext
} from '../__fixtures__';
import type { DiffResultTextFile } from '../../typings';

describe('log', () => {
let context: SimpleGitTestContext;
Expand Down Expand Up @@ -50,10 +52,64 @@ describe('log', () => {
]);
});

it('should read one line for each commit when using shortstat', async () => {
const options = ['--shortstat'];
const actual = await newSimpleGit(context.root).log(options);
describe('log formats', () => {
const a = 'a.txt';
const b = 'b.txt';

function file(file: string, changes = 0, insertions = 0, deletions = 0): DiffResultTextFile {
return {
file,
changes,
insertions,
deletions,
binary: false,
}
}

function out(file: DiffResultTextFile, changed = 0, insertions = 0, deletions = 0) {
return {
diff: {
changed,
deletions,
insertions,
files: [file]
}
};
}

it('should read one line for each commit when using shortstat', async () => {
const options = ['--shortstat'];
const actual = await newSimpleGit(context.root).log(options);

expect(actual.all).toHaveLength(2);
});

it('should work using numstat', async () => {
const options = ['--numstat'];
const actual = await newSimpleGit(context.root).log(options);
expect(actual).toEqual(like({
all: [
like(out(file(b,1, 1), 1, 1)),
like(out(file(a, 1, 1), 1, 1)),
]
}))
});

it('should work name only (summary has count of file changes, files show no count data)', async () => {
const options = ['--name-only'];
const actual = await newSimpleGit(context.root).log(options);
expect(actual).toEqual(like({
all: [
like(out(file(b, 0), 1)),
like(out(file(a, 0), 1)),
]
}))
});

it('should fail when using multiple summary types', async () => {
const result = await promiseResult(newSimpleGit(context.root).log(['--stat', '--numstat']));

expect(actual.all).toHaveLength(2);
expect(result.threw).toBe(true);
});
});
});
Loading

0 comments on commit fd29242

Please sign in to comment.