-
Notifications
You must be signed in to change notification settings - Fork 12.1k
Expand file tree
/
Copy pathupdate.ts
More file actions
131 lines (125 loc) · 3.85 KB
/
update.ts
File metadata and controls
131 lines (125 loc) · 3.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import type { CommandModule } from 'yargs';
import {
loadExtensions,
annotateActiveExtensions,
} from '../../config/extension.js';
import {
updateAllUpdatableExtensions,
type ExtensionUpdateInfo,
checkForAllExtensionUpdates,
updateExtension,
} from '../../config/extensions/update.js';
import { checkForExtensionUpdate } from '../../config/extensions/github.js';
import { getErrorMessage } from '../../utils/errors.js';
import { ExtensionUpdateState } from '../../ui/state/extensions.js';
interface UpdateArgs {
name?: string;
all?: boolean;
}
const updateOutput = (info: ExtensionUpdateInfo) =>
`Extension "${info.name}" successfully updated: ${info.originalVersion} → ${info.updatedVersion}.`;
export async function handleUpdate(args: UpdateArgs) {
const workingDir = process.cwd();
const allExtensions = loadExtensions();
const extensions = annotateActiveExtensions(
allExtensions,
allExtensions.map((e) => e.config.name),
workingDir,
);
if (args.all) {
try {
let updateInfos = await updateAllUpdatableExtensions(
workingDir,
extensions,
await checkForAllExtensionUpdates(extensions, new Map(), (_) => {}),
() => {},
);
updateInfos = updateInfos.filter(
(info) => info.originalVersion !== info.updatedVersion,
);
if (updateInfos.length === 0) {
console.log('No extensions to update.');
return;
}
console.log(updateInfos.map((info) => updateOutput(info)).join('\n'));
} catch (error) {
console.error(getErrorMessage(error));
}
}
if (args.name)
try {
const extension = extensions.find(
(extension) => extension.name === args.name,
);
if (!extension) {
console.log(`Extension "${args.name}" not found.`);
return;
}
let updateState: ExtensionUpdateState | undefined;
if (!extension.installMetadata) {
console.log(
`Unable to install extension "${args.name}" due to missing install metadata`,
);
return;
}
await checkForExtensionUpdate(extension, (newState) => {
updateState = newState;
});
if (updateState !== ExtensionUpdateState.UPDATE_AVAILABLE) {
console.log(`Extension "${args.name}" is already up to date.`);
return;
}
// TODO(chrstnb): we should list extensions if the requested extension is not installed.
const updatedExtensionInfo = (await updateExtension(
extension,
workingDir,
updateState,
() => {},
))!;
if (
updatedExtensionInfo.originalVersion !==
updatedExtensionInfo.updatedVersion
) {
console.log(
`Extension "${args.name}" successfully updated: ${updatedExtensionInfo.originalVersion} → ${updatedExtensionInfo.updatedVersion}.`,
);
} else {
console.log(`Extension "${args.name}" is already up to date.`);
}
} catch (error) {
console.error(getErrorMessage(error));
}
}
export const updateCommand: CommandModule = {
command: 'update [--all] [name]',
describe:
'Updates all extensions or a named extension to the latest version.',
builder: (yargs) =>
yargs
.positional('name', {
describe: 'The name of the extension to update.',
type: 'string',
})
.option('all', {
describe: 'Update all extensions.',
type: 'boolean',
})
.conflicts('name', 'all')
.check((argv) => {
if (!argv.all && !argv.name) {
throw new Error('Either an extension name or --all must be provided');
}
return true;
}),
handler: async (argv) => {
await handleUpdate({
name: argv['name'] as string | undefined,
all: argv['all'] as boolean | undefined,
});
},
};