Skip to content

Commit

Permalink
fix(dotnet): prevent "false" being incorrectly passed to dotnet command
Browse files Browse the repository at this point in the history
  • Loading branch information
EchelonFour committed Jan 17, 2024
1 parent b673b2f commit e04924a
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 6 deletions.
46 changes: 46 additions & 0 deletions packages/dotnet/src/lib/core/dotnet.client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,4 +484,50 @@ ASP.NET Core gRPC Service grpc [C#]
`);
});
});

describe('test', () => {
it('should call test command', () => {
const dotnetClient = new DotNetClient(mockDotnetFactory('6.0.0'));
const spy = jest
.spyOn(dotnetClient, 'logAndExecute')
.mockImplementation(() => ({}));
dotnetClient.test('my-project', false, {
blame: false,
});
expect(spy).toHaveBeenCalledTimes(1);
expect(spy.mock.calls).toMatchInlineSnapshot(`
[
[
[
"test",
"my-project",
],
],
]
`);
});
});

describe('build', () => {
it('should call build command', () => {
const dotnetClient = new DotNetClient(mockDotnetFactory('6.0.0'));
const spy = jest
.spyOn(dotnetClient, 'logAndExecute')
.mockImplementation(() => ({}));
dotnetClient.build('my-project', {
noDependencies: false,
});
expect(spy).toHaveBeenCalledTimes(1);
expect(spy.mock.calls).toMatchInlineSnapshot(`
[
[
[
"build",
"my-project",
],
],
]
`);
});
});
});
14 changes: 12 additions & 2 deletions packages/dotnet/src/lib/core/dotnet.client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { ChildProcess, spawn, spawnSync } from 'child_process';
import * as semver from 'semver';

import { getSpawnParameterArray, swapKeysUsingMap } from '@nx-dotnet/utils';
import {
getSpawnParameterArray,
swapExplicitFalseKeys,
swapKeysUsingMap,
} from '@nx-dotnet/utils';

import {
addPackageKeyMap,
Expand All @@ -14,6 +18,7 @@ import {
dotnetRunOptions,
DotnetTemplate,
dotnetTestOptions,
formatExplicitFalseFlags,
formatKeyMap,
KnownDotnetTemplates,
newKeyMap,
Expand Down Expand Up @@ -260,7 +265,12 @@ export class DotNetClient {
params.push(project);
if (parameters) {
params.push(
...getSpawnParameterArray(swapKeysUsingMap(parameters, formatKeyMap)),
...getSpawnParameterArray(
swapKeysUsingMap(
swapExplicitFalseKeys(parameters, formatExplicitFalseFlags),
formatKeyMap,
),
),
);
}
return this.logAndExecute(params);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ export const formatKeyMap: Partial<{ [key in dotnetFormatFlags]: string }> = {
fixAnalyzers: 'fix-analyzers',
verifyNoChanges: 'verify-no-changes',
};

export const formatExplicitFalseFlags: readonly dotnetFormatFlags[] = [
'fixAnalyzers',
'fixStyle',
'fixWhitespace',
];
24 changes: 23 additions & 1 deletion packages/utils/src/lib/utility-functions/args.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isDryRun } from './args';
import { isDryRun, swapExplicitFalseKeys } from './args';

describe('Args util functions', () => {
describe('isDryRun', () => {
Expand All @@ -9,4 +9,26 @@ describe('Args util functions', () => {
expect({ before, after }).toStrictEqual({ before: false, after: true });
});
});

describe('swapExplicitFalseKeys', () => {
it('should change a value to the string "false" if in the explicit false list', () => {
const result = swapExplicitFalseKeys(
{
fixWhitespace: false,
fixStyle: true,
fixAnalyzers: false,
noBuild: false,
noDependencies: true,
},
['fixWhitespace', 'fixStyle', 'fixAnalyzers'],
);
expect(result).toStrictEqual({
fixWhitespace: 'false',
fixStyle: true,
fixAnalyzers: 'false',
noBuild: false,
noDependencies: true,
});
});
});
});
14 changes: 14 additions & 0 deletions packages/utils/src/lib/utility-functions/args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,17 @@ export function swapKeysUsingMap(
]),
);
}

export function swapExplicitFalseKeys<
TRecord extends Record<string, string | boolean>,
>(
object: TRecord,
explicitFalseKeys: readonly (keyof TRecord)[],
): Record<string, string | boolean> {
return Object.fromEntries(
Object.entries(object).map(([key, value]) => [
key,
explicitFalseKeys.includes(key) && value === false ? 'false' : value,
]),
) as Record<string, string | boolean>;
}
7 changes: 4 additions & 3 deletions packages/utils/src/lib/utility-functions/parameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ export function getSpawnParameterArray(
): string[] {
const spawnArray: string[] = [];
for (const [key, value] of Object.entries(parameters)) {
// true booleans are flags, explicit false booleans follow regular key-value pattern
if (typeof value === 'boolean' && value) {
spawnArray.push(`--${key}`);
if (typeof value === 'boolean') {
if (value) {
spawnArray.push(`--${key}`);
}
} else if (value !== undefined && value !== null) {
spawnArray.push(`--${key}`, value.toString());
}
Expand Down

0 comments on commit e04924a

Please sign in to comment.