Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,22 @@ export async function runCli(argv: readonly string[], backend: CommandBackend):
process.stderr.write(`${backend.help}\n`);
return 1;
}
if (command === 'help' || command === '--help' || command === '-h') {
if (command === 'help') {
const path = argv.slice(1);
if (
path.length === 0 ||
(path.length === 1 && (path[0] === 'help' || path[0] === '--help' || path[0] === '-h'))
) {
process.stdout.write(`${backend.help}\n`);
return 0;
}
if (path.some((argument) => argument.startsWith('-'))) {
process.stderr.write('gcb: help takes a command path, not options\n');
return 1;
}
return runCli([...path, '--help'], backend);
}
if (command === '--help' || command === '-h') {
process.stdout.write(`${backend.help}\n`);
return 0;
}
Expand Down
16 changes: 16 additions & 0 deletions test/unit/commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1247,3 +1247,19 @@ describe('the anchor flags, at the CLI boundary', () => {
assert.doesNotMatch(noNumber.stderr, /--number is required/, 'without being asked for a number');
});
});

describe('the help path', () => {
it('routes gcb help pr to gcb pr --help', () => {
const home = fs.mkdtempSync(path.join(os.tmpdir(), 'gcb-help-path-'));
try {
const result = execFileSync('node', ['--conditions=development', 'packages/client/bin/gcb.js', 'help', 'pr'], {
cwd: path.resolve('.'),
encoding: 'utf8',
env: { ...process.env, HOME: home, GIT_BROKER_SOCKET: '', GIT_BROKER_SOCKET_FILE: '' },
});
assert.match(result, /Usage: gcb pr/);
} finally {
fs.rmSync(home, { recursive: true, force: true });
}
});
});
45 changes: 45 additions & 0 deletions test/unit/gh-command.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,3 +418,48 @@ describe('the -- terminator', () => {
assert.match(result.stderr, /too many positional arguments/);
});
});

describe('the help path', () => {
it('routes gcb help gh pr to gh pr --help', async () => {
const result = await runClient(['help', 'gh', 'pr']);
assert.equal(result.status, 0);
assert.match(result.stdout, /Usage: gcb gh/);
});
});

describe('a help path that is the help command', () => {
it('prints root help for help --help and help help', async () => {
for (const args of [['help', '--help'], ['help', 'help']]) {
const result = await runClient(args);
assert.equal(result.status, 0, args.join(' '));
assert.match(result.stdout, /Usage: gcb/);
}
});
});

describe('an invalid help path', () => {
it('does not run a command when the path contains options', async () => {
for (const args of [
['help', 'pr', '--'],
['help', 'pr', '--number'],
['help', 'pr', '--help'],
]) {
const result = await runClient(args);
assert.equal(result.status, 1, args.join(' '));
assert.match(result.stderr, /help takes a command path/);
}
});
});

describe('command-specific help refusal', () => {
it('runs the dispatcher checks for help host', async () => {
const result = await runClient(['help', 'host']);
assert.equal(result.status, 1);
assert.equal(result.stdout, '');
if (process.platform === 'win32') {
assert.match(result.stderr, /native Windows is not supported/);
} else {
assert.match(result.stderr, /`host` is a host command; install gcb-host on the host/);
}
});
});
Loading