mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-28 22:14:52 -07:00
fix(cli): list installed extensions when update target missing (#17082)
This commit is contained in:
@@ -24,6 +24,7 @@ import { ExtensionUpdateState } from '../../ui/state/extensions.js';
|
|||||||
|
|
||||||
// Mock dependencies
|
// Mock dependencies
|
||||||
const emitConsoleLog = vi.hoisted(() => vi.fn());
|
const emitConsoleLog = vi.hoisted(() => vi.fn());
|
||||||
|
const emitFeedback = vi.hoisted(() => vi.fn());
|
||||||
const debugLogger = vi.hoisted(() => ({
|
const debugLogger = vi.hoisted(() => ({
|
||||||
log: vi.fn((message, ...args) => {
|
log: vi.fn((message, ...args) => {
|
||||||
emitConsoleLog('log', format(message, ...args));
|
emitConsoleLog('log', format(message, ...args));
|
||||||
@@ -40,6 +41,7 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
|
|||||||
...actual,
|
...actual,
|
||||||
coreEvents: {
|
coreEvents: {
|
||||||
emitConsoleLog,
|
emitConsoleLog,
|
||||||
|
emitFeedback,
|
||||||
},
|
},
|
||||||
debugLogger,
|
debugLogger,
|
||||||
};
|
};
|
||||||
@@ -84,6 +86,42 @@ describe('extensions update command', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('handleUpdate', () => {
|
describe('handleUpdate', () => {
|
||||||
|
it('should list installed extensions when requested extension is not found', async () => {
|
||||||
|
const mockCwd = vi.spyOn(process, 'cwd').mockReturnValue('/test/dir');
|
||||||
|
const extensions = [
|
||||||
|
{ name: 'ext1', version: '1.0.0' },
|
||||||
|
{ name: 'ext2', version: '2.0.0' },
|
||||||
|
];
|
||||||
|
mockExtensionManager.prototype.loadExtensions = vi
|
||||||
|
.fn()
|
||||||
|
.mockResolvedValue(extensions);
|
||||||
|
|
||||||
|
await handleUpdate({ name: 'missing-extension' });
|
||||||
|
|
||||||
|
expect(emitFeedback).toHaveBeenCalledWith(
|
||||||
|
'error',
|
||||||
|
'Extension "missing-extension" not found.\n\nInstalled extensions:\next1 (1.0.0)\next2 (2.0.0)\n\nRun "gemini extensions list" for details.',
|
||||||
|
);
|
||||||
|
expect(mockUpdateExtension).not.toHaveBeenCalled();
|
||||||
|
mockCwd.mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should log a helpful message when no extensions are installed and requested extension is not found', async () => {
|
||||||
|
const mockCwd = vi.spyOn(process, 'cwd').mockReturnValue('/test/dir');
|
||||||
|
mockExtensionManager.prototype.loadExtensions = vi
|
||||||
|
.fn()
|
||||||
|
.mockResolvedValue([]);
|
||||||
|
|
||||||
|
await handleUpdate({ name: 'missing-extension' });
|
||||||
|
|
||||||
|
expect(emitFeedback).toHaveBeenCalledWith(
|
||||||
|
'error',
|
||||||
|
'Extension "missing-extension" not found.\n\nNo extensions installed.',
|
||||||
|
);
|
||||||
|
expect(mockUpdateExtension).not.toHaveBeenCalled();
|
||||||
|
mockCwd.mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
{
|
{
|
||||||
state: ExtensionUpdateState.UPDATE_AVAILABLE,
|
state: ExtensionUpdateState.UPDATE_AVAILABLE,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
import { checkForExtensionUpdate } from '../../config/extensions/github.js';
|
import { checkForExtensionUpdate } from '../../config/extensions/github.js';
|
||||||
import { getErrorMessage } from '../../utils/errors.js';
|
import { getErrorMessage } from '../../utils/errors.js';
|
||||||
import { ExtensionUpdateState } from '../../ui/state/extensions.js';
|
import { ExtensionUpdateState } from '../../ui/state/extensions.js';
|
||||||
import { debugLogger } from '@google/gemini-cli-core';
|
import { coreEvents, debugLogger } from '@google/gemini-cli-core';
|
||||||
import { ExtensionManager } from '../../config/extension-manager.js';
|
import { ExtensionManager } from '../../config/extension-manager.js';
|
||||||
import { requestConsentNonInteractive } from '../../config/extensions/consent.js';
|
import { requestConsentNonInteractive } from '../../config/extensions/consent.js';
|
||||||
import { loadSettings } from '../../config/settings.js';
|
import { loadSettings } from '../../config/settings.js';
|
||||||
@@ -46,7 +46,21 @@ export async function handleUpdate(args: UpdateArgs) {
|
|||||||
(extension) => extension.name === args.name,
|
(extension) => extension.name === args.name,
|
||||||
);
|
);
|
||||||
if (!extension) {
|
if (!extension) {
|
||||||
debugLogger.log(`Extension "${args.name}" not found.`);
|
if (extensions.length === 0) {
|
||||||
|
coreEvents.emitFeedback(
|
||||||
|
'error',
|
||||||
|
`Extension "${args.name}" not found.\n\nNo extensions installed.`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const installedExtensions = extensions
|
||||||
|
.map((extension) => `${extension.name} (${extension.version})`)
|
||||||
|
.join('\n');
|
||||||
|
coreEvents.emitFeedback(
|
||||||
|
'error',
|
||||||
|
`Extension "${args.name}" not found.\n\nInstalled extensions:\n${installedExtensions}\n\nRun "gemini extensions list" for details.`,
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!extension.installMetadata) {
|
if (!extension.installMetadata) {
|
||||||
@@ -63,7 +77,6 @@ export async function handleUpdate(args: UpdateArgs) {
|
|||||||
debugLogger.log(`Extension "${args.name}" is already up to date.`);
|
debugLogger.log(`Extension "${args.name}" is already up to date.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO(chrstnb): we should list extensions if the requested extension is not installed.
|
|
||||||
const updatedExtensionInfo = (await updateExtension(
|
const updatedExtensionInfo = (await updateExtension(
|
||||||
extension,
|
extension,
|
||||||
extensionManager,
|
extensionManager,
|
||||||
|
|||||||
Reference in New Issue
Block a user