| // Copyright 2024 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import * as vscode from 'vscode'; |
| import { window } from 'vscode'; |
| import { Setup } from './extension'; |
| import * as logger from './logger'; |
| |
| /** |
| * initialize fuchsia workflow interaction commands |
| */ |
| export function setUpWorkflowInteraction(ctx: vscode.ExtensionContext, setup: Setup) { |
| vscode.commands.registerCommand( |
| 'fuchsia.fx.set', |
| async (product?: string, board?: string, packages?: string) => { |
| let status: Record<string, string> = { |
| 'product': '', |
| 'board': '' |
| }; |
| await getStatus(status); |
| |
| if (!product) { |
| await getList('list-products', status.product).then(async (list) => { |
| const selected = await window.showQuickPick(list, { |
| title: 'Select Product' |
| }); |
| product = selected?.label; |
| }); |
| } |
| |
| if (!board) { |
| await getList('list-boards', status.board).then(async (list) => { |
| const selected = await window.showQuickPick(list, { |
| title: 'Select Board' |
| }); |
| board = selected?.label; |
| }); |
| } |
| |
| if (!packages) { |
| packages = await window.showInputBox({ |
| placeHolder: '(e.g. //examples //examples:tests)', |
| prompt: 'Enter packages to include in universe' |
| }); |
| } |
| |
| if (!product || !board) { |
| return; |
| } |
| |
| let args = ['set', `${product?.trimEnd()}.${board?.trimEnd()}`]; |
| if (packages) { |
| let packageList = packages?.split(' '); |
| packageList?.forEach(packageItem => { |
| args.push('--with'); |
| args.push(packageItem); |
| }); |
| } |
| |
| void window.withProgress({ |
| location: vscode.ProgressLocation.Notification, |
| title: 'fx set', |
| cancellable: true |
| }, async (progress, token) => { |
| let cmd = setup.fx.runAsync( |
| args, |
| () => void window.showInformationMessage('fx set completed'), |
| handleErr |
| ); |
| |
| token.onCancellationRequested(() => { |
| console.log('User canceled fx build operation'); |
| cmd?.stop(); |
| }); |
| |
| let exitCode = await cmd?.exitCode; |
| return exitCode === 0 ? Promise.resolve() : Promise.reject(exitCode); |
| }); |
| |
| /** Get current target configuration */ |
| async function getStatus(status: Record<string, string>) { |
| const process = setup.fx.runJsonStreaming(['status', '--format=json'], (data: any) => { |
| status.product = data.buildInfo.items.products.value; |
| status.board = data.buildInfo.items.boards.value; |
| }); |
| await process.exitCode; |
| } |
| |
| /** |
| * get list of results from fx command |
| * @param args fx command to run |
| */ |
| async function getList(arg: string, last: string): Promise<vscode.QuickPickItem[]> { |
| let data: vscode.QuickPickItem[] = []; |
| let cmd = setup.fx.runAsync( |
| [arg], |
| (buffer: Buffer) => { |
| const msg = new TextDecoder().decode(buffer); |
| if (msg.includes('ERROR')) { |
| void window.showErrorMessage(msg); |
| } else { |
| let items = msg.split('\n').filter(item => item); |
| items.forEach((item) => { |
| if (item === last) { |
| data.unshift({ |
| label: item, |
| description: '(Current)' |
| }); |
| return; |
| } |
| data.push({ |
| label: item |
| }); |
| }); |
| } |
| }, |
| handleErr); |
| let exitCode = await cmd?.exitCode; |
| return exitCode === 0 ? Promise.resolve(data) : Promise.reject(exitCode); |
| } |
| |
| // TODO(https://fxbug.dev/369839772): handle errs w/ task problem matcher |
| /** |
| * handle errs from callback |
| */ |
| function handleErr(buffer: Buffer) { |
| const msg = new TextDecoder().decode(buffer); |
| void window.showErrorMessage(msg); |
| } |
| } |
| ); |
| |
| vscode.commands.registerCommand('fuchsia.fx.build', () => { |
| void window.withProgress({ |
| location: vscode.ProgressLocation.Notification, |
| title: 'fx build', |
| cancellable: true |
| }, async (progress, token) => { |
| let cmd = setup.fx.runAsync(['build'], handleData, handleData); |
| let percentage: number; |
| |
| token.onCancellationRequested(() => { |
| console.log('User canceled fx build operation'); |
| cmd?.stop(); |
| }); |
| |
| /** |
| * callback to handle buffer from process |
| */ |
| function handleData(buffer: Buffer) { |
| const msg = new TextDecoder().decode(buffer); |
| // TODO(https://fxbug.dev/369839772): handle errs w/ task problem matcher |
| if (msg.includes('ERROR') || msg.includes('credentials')) { |
| void window.showErrorMessage(msg); |
| } |
| if (msg.includes('Locked')) { |
| void window.showWarningMessage(msg); |
| } |
| if (msg.includes('no work to do')) { |
| void window.showInformationMessage(msg); |
| } |
| // TODO(https://fxbug.dev/375234893): move msg to output window |
| if (msg.includes('%')) { |
| let match = msg.match(/\d+%/); |
| if (match) { |
| let lastPercent = percentage ?? 0; |
| percentage = parseInt(match[0]); |
| progress.report({ increment: percentage - lastPercent, message: `\n ${msg}` }); |
| } |
| } |
| if (msg.includes('actions')) { |
| progress.report({ message: `${msg}` }); |
| } |
| } |
| |
| let exitCode = await cmd?.exitCode; |
| return exitCode === 0 ? Promise.resolve() : Promise.reject(exitCode); |
| }); |
| }); |
| |
| vscode.commands.registerCommand('fuchsia.fx.serve', () => { |
| void window.withProgress({ |
| location: vscode.ProgressLocation.Notification, |
| title: 'fx serve', |
| cancellable: true |
| }, async (progress, token) => { |
| let cmd = setup.fx.runAsync(['serve', '--background'], handleData, handleData); |
| |
| token.onCancellationRequested(() => { |
| console.log('User canceled fx serve operation'); |
| cmd?.stop(); |
| }); |
| |
| let exitCode = await cmd?.exitCode; |
| return exitCode === 0 ? Promise.resolve() : Promise.reject(exitCode); |
| |
| /** callback to handle buffer from process */ |
| function handleData(buffer: Buffer) { |
| const msg = new TextDecoder().decode(buffer); |
| logger.info(msg, 'fuchsia'); |
| if (msg.includes('resolve')) { |
| let match = msg.match(/(.*) (\[\w+\])\s+(.*)/); |
| if (match) { |
| progress.report({ message: `${match[match.length - 1]}` }); |
| } |
| } |
| } |
| }); |
| }); |
| |
| vscode.commands.registerCommand('fuchsia.repository.server.stop', () => { |
| setup.ffx.runFfx(['repository', 'server', 'stop']) |
| .then(() => { |
| logger.info('Stopped the repository server'); |
| }) |
| .catch((err) => { |
| logger.error(err); |
| }); |
| }); |
| } |