Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --parallel/--no-parallel option to download:plugins #11112

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
61 changes: 46 additions & 15 deletions dev-packages/cli/src/download-plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,26 @@ export interface DownloadPluginsOptions {
* The open-vsx registry API url.
*/
apiUrl?: string;

/**
* Fetch plugins in parallel
*/
parallel?: boolean;
}

interface PluginDownload {
id: string,
downloadUrl: string,
version?: string | undefined
}

export default async function downloadPlugins(options: DownloadPluginsOptions = {}): Promise<void> {
const {
packed = false,
ignoreErrors = false,
apiVersion = DEFAULT_SUPPORTED_API_VERSION,
apiUrl = 'https://open-vsx.org/api'
apiUrl = 'https://open-vsx.org/api',
parallel = true
} = options;

// Collect the list of failures to be appended at the end of the script.
Expand All @@ -88,6 +100,19 @@ export default async function downloadPlugins(options: DownloadPluginsOptions =
// Excluded extension ids.
const excludedIds = new Set<string>(pck.theiaPluginsExcludeIds || []);

// Downloader wrapper
const downloadPlugin = (plugin: PluginDownload): Promise<void> => downloadPluginAsync(failures, plugin.id, plugin.downloadUrl, pluginsDir, packed, plugin.version);

const downloader = async (plugins: PluginDownload[]) => {
if (parallel) {
await Promise.all(plugins.map(downloadPlugin));
} else {
for (const plugin of plugins) {
await downloadPlugin(plugin);
}
}
};

await fs.mkdir(pluginsDir, { recursive: true });

if (!pck.theiaPlugins) {
Expand All @@ -98,14 +123,10 @@ export default async function downloadPlugins(options: DownloadPluginsOptions =
console.warn('--- downloading plugins ---');
// Download the raw plugins defined by the `theiaPlugins` property.
// This will include both "normal" plugins as well as "extension packs".
const downloads = [];
for (const [plugin, pluginUrl] of Object.entries(pck.theiaPlugins)) {
if (typeof pluginUrl !== 'string') {
continue;
}
downloads.push(downloadPluginAsync(failures, plugin, pluginUrl, pluginsDir, packed));
}
await Promise.all(downloads);
const pluginsToDownload = Object.entries(pck.theiaPlugins)
.filter((entry: [string, unknown]): entry is [string, string] => typeof entry[1] === 'string')
.map(([pluginId, url]: [string, string]) => <PluginDownload>{ id: pluginId, downloadUrl: url });
await downloader(pluginsToDownload);

console.warn('--- collecting extension-packs ---');
const extensionPacks = await collectExtensionPacks(pluginsDir, excludedIds);
Expand All @@ -114,13 +135,18 @@ export default async function downloadPlugins(options: DownloadPluginsOptions =
const client = new OVSXClient({ apiVersion, apiUrl });
// De-duplicate extension ids to only download each once:
const ids = new Set<string>(Array.from(extensionPacks.values()).flat());
await Promise.all(Array.from(ids, async id => {
const extensionPacksToDownload: PluginDownload[] = [];
for (const id of ids) {
const extension = await client.getLatestCompatibleExtensionVersion(id);
const version = extension?.version;
const downloadUrl = extension?.files.download;
if (downloadUrl) {
await downloadPluginAsync(failures, id, downloadUrl, pluginsDir, packed, extension?.version);
extensionPacksToDownload.push({ id: id, downloadUrl: downloadUrl, version: version });
} else {
failures.push(`No download url for extension pack ${id} (${version})`);
}
}));
}
await downloader(extensionPacksToDownload);
}

console.warn('--- collecting extension dependencies ---');
Expand All @@ -130,13 +156,18 @@ export default async function downloadPlugins(options: DownloadPluginsOptions =
const client = new OVSXClient({ apiVersion, apiUrl });
// De-duplicate extension ids to only download each once:
const ids = new Set<string>(pluginDependencies);
await Promise.all(Array.from(ids, async id => {
const extensionDependenciesToDownload: PluginDownload[] = [];
for (const id of ids) {
const extension = await client.getLatestCompatibleExtensionVersion(id);
const version = extension?.version;
const downloadUrl = extension?.files.download;
if (downloadUrl) {
await downloadPluginAsync(failures, id, downloadUrl, pluginsDir, packed, extension?.version);
extensionDependenciesToDownload.push({ id: id, downloadUrl: downloadUrl, version: version });
} else {
failures.push(`No download url for extension dependency ${id} (${version})`);
}
}));
}
await downloader(extensionDependenciesToDownload);
}

} finally {
Expand Down
15 changes: 12 additions & 3 deletions dev-packages/cli/src/theia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,11 @@ async function theiaCli(): Promise<void> {
}
})
.command<{
packed: boolean
packed: boolean,
ignoreErrors: boolean,
apiVersion: string,
apiUrl: string,
parallel: boolean
}>({
command: 'download:plugins',
describe: 'Download defined external plugins',
Expand All @@ -223,10 +227,15 @@ async function theiaCli(): Promise<void> {
alias: 'u',
describe: 'Open-VSX Registry API URL',
default: 'https://open-vsx.org/api'
},
'parallel': {
describe: 'Download in parallel',
boolean: true,
default: true
}
},
handler: async ({ packed }) => {
await downloadPlugins({ packed });
handler: async ({ packed, ignoreErrors, apiVersion, apiUrl, parallel }) => {
await downloadPlugins({ packed, ignoreErrors, apiVersion, apiUrl, parallel });
},
})
.command<{
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
"vscode.git-ui",
"vscode.github",
"vscode.github-authentication",
"vscode.microsoft-authentication"
"vscode.microsoft-authentication",
"ms-vscode.js-debug-companion"
]
}