mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-10-25 02:58:33 +00:00
feat: use Arduino CLI 0.36.0-rc.1 APIs
Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
@@ -3,7 +3,6 @@ import { nls } from '@theia/core/lib/common/nls';
|
||||
import { notEmpty } from '@theia/core/lib/common/objects';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
Board,
|
||||
BoardDetails,
|
||||
BoardSearch,
|
||||
BoardUserField,
|
||||
@@ -32,11 +31,9 @@ import {
|
||||
BoardListAllResponse,
|
||||
BoardSearchRequest,
|
||||
} from './cli-protocol/cc/arduino/cli/commands/v1/board_pb';
|
||||
import { Platform } from './cli-protocol/cc/arduino/cli/commands/v1/common_pb';
|
||||
import { PlatformSummary } from './cli-protocol/cc/arduino/cli/commands/v1/common_pb';
|
||||
import {
|
||||
PlatformInstallRequest,
|
||||
PlatformListRequest,
|
||||
PlatformListResponse,
|
||||
PlatformSearchRequest,
|
||||
PlatformSearchResponse,
|
||||
PlatformUninstallRequest,
|
||||
@@ -247,24 +244,22 @@ export class BoardsServiceImpl
|
||||
|
||||
async getInstalledPlatforms(): Promise<BoardsPackage[]> {
|
||||
const { instance, client } = await this.coreClient;
|
||||
return new Promise<BoardsPackage[]>((resolve, reject) => {
|
||||
client.platformList(
|
||||
new PlatformListRequest().setInstance(instance),
|
||||
(err, response) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve(
|
||||
response
|
||||
.getInstalledPlatformsList()
|
||||
.map((platform, _, installedPlatforms) =>
|
||||
toBoardsPackage(platform, installedPlatforms)
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
const resp = await new Promise<PlatformSearchResponse>(
|
||||
(resolve, reject) => {
|
||||
client.platformSearch(
|
||||
new PlatformSearchRequest()
|
||||
.setInstance(instance)
|
||||
.setManuallyInstalled(true), // include core manually installed to the sketchbook
|
||||
(err, resp) => (err ? reject(err) : resolve(resp))
|
||||
);
|
||||
}
|
||||
);
|
||||
const searchOutput = resp.getSearchOutputList();
|
||||
return searchOutput
|
||||
.map((message) => message.toObject(false))
|
||||
.filter((summary) => summary.installedVersion) // only installed ones
|
||||
.map(createBoardsPackage)
|
||||
.filter(notEmpty);
|
||||
}
|
||||
|
||||
private async handleListBoards(
|
||||
@@ -287,12 +282,28 @@ export class BoardsServiceImpl
|
||||
for (const board of resp.getBoardsList()) {
|
||||
const platform = board.getPlatform();
|
||||
if (platform) {
|
||||
const platformId = platform.getId();
|
||||
const metadata = platform.getMetadata();
|
||||
if (!metadata) {
|
||||
console.warn(
|
||||
`Platform metadata is missing for platform: ${JSON.stringify(
|
||||
platform.toObject(false)
|
||||
)}. Skipping`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
const platformId = metadata.getId();
|
||||
const release = platform.getRelease();
|
||||
if (!release) {
|
||||
console.warn(
|
||||
`Platform release is missing for platform: ${platformId}. Skipping`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
const fqbn = board.getFqbn() || undefined; // prefer undefined over empty string
|
||||
const parsedPlatformId = createPlatformIdentifier(platformId);
|
||||
if (!parsedPlatformId) {
|
||||
console.warn(
|
||||
`Could not create platform identifier from platform ID input: ${platform.getId()}. Skipping`
|
||||
`Could not create platform identifier from platform ID input: ${platformId}. Skipping`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
@@ -319,8 +330,8 @@ export class BoardsServiceImpl
|
||||
name: board.getName(),
|
||||
fqbn: board.getFqbn(),
|
||||
packageId: parsedPlatformId,
|
||||
packageName: platform.getName(),
|
||||
manuallyInstalled: platform.getManuallyInstalled(),
|
||||
packageName: release.getName(),
|
||||
manuallyInstalled: metadata.getManuallyInstalled(),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -375,89 +386,25 @@ export class BoardsServiceImpl
|
||||
const coreClient = await this.coreClient;
|
||||
const { client, instance } = coreClient;
|
||||
|
||||
const installedPlatformsReq = new PlatformListRequest();
|
||||
installedPlatformsReq.setInstance(instance);
|
||||
const installedPlatformsResp = await new Promise<PlatformListResponse>(
|
||||
(resolve, reject) => {
|
||||
client.platformList(installedPlatformsReq, (err, resp) => {
|
||||
!!err ? reject(err) : resolve(resp);
|
||||
});
|
||||
}
|
||||
);
|
||||
const installedPlatforms =
|
||||
installedPlatformsResp.getInstalledPlatformsList();
|
||||
|
||||
const req = new PlatformSearchRequest();
|
||||
req.setSearchArgs(options.query || '');
|
||||
req.setAllVersions(true);
|
||||
req.setInstance(instance);
|
||||
// `core search` returns with all platform versions when the command is executed via gRPC or with `--format json`
|
||||
// The `--all` flag is applicable only when filtering for the human-readable (`--format text`) output of the CLI
|
||||
const resp = await new Promise<PlatformSearchResponse>(
|
||||
(resolve, reject) => {
|
||||
client.platformSearch(req, (err, resp) => {
|
||||
!!err ? reject(err) : resolve(resp);
|
||||
});
|
||||
client.platformSearch(
|
||||
new PlatformSearchRequest()
|
||||
.setInstance(instance)
|
||||
.setSearchArgs(options.query ?? ''),
|
||||
(err, resp) => (err ? reject(err) : resolve(resp))
|
||||
);
|
||||
}
|
||||
);
|
||||
const packages = new Map<string, BoardsPackage>();
|
||||
// We must group the cores by ID, and sort platforms by, first the installed version, then version alphabetical order.
|
||||
// Otherwise we lose the FQBN information.
|
||||
const groupedById: Map<string, Platform[]> = new Map();
|
||||
for (const platform of resp.getSearchOutputList()) {
|
||||
const id = platform.getId();
|
||||
const idGroup = groupedById.get(id);
|
||||
if (idGroup) {
|
||||
idGroup.push(platform);
|
||||
} else {
|
||||
groupedById.set(id, [platform]);
|
||||
}
|
||||
}
|
||||
const installedAwareVersionComparator = (
|
||||
left: Platform,
|
||||
right: Platform
|
||||
) => {
|
||||
// XXX: we cannot rely on `platform.getInstalled()`, it is always an empty string.
|
||||
const leftInstalled = !!installedPlatforms.find(
|
||||
(ip) =>
|
||||
ip.getId() === left.getId() && ip.getInstalled() === left.getLatest()
|
||||
);
|
||||
const rightInstalled = !!installedPlatforms.find(
|
||||
(ip) =>
|
||||
ip.getId() === right.getId() &&
|
||||
ip.getInstalled() === right.getLatest()
|
||||
);
|
||||
if (leftInstalled && !rightInstalled) {
|
||||
return -1;
|
||||
}
|
||||
if (!leftInstalled && rightInstalled) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const invertedVersionComparator =
|
||||
Installable.Version.COMPARATOR(left.getLatest(), right.getLatest()) *
|
||||
-1;
|
||||
// Higher version comes first.
|
||||
|
||||
return invertedVersionComparator;
|
||||
};
|
||||
for (const value of groupedById.values()) {
|
||||
value.sort(installedAwareVersionComparator);
|
||||
}
|
||||
|
||||
for (const value of groupedById.values()) {
|
||||
for (const platform of value) {
|
||||
const id = platform.getId();
|
||||
const pkg = packages.get(id);
|
||||
if (pkg) {
|
||||
pkg.availableVersions.push(platform.getLatest());
|
||||
pkg.availableVersions.sort(Installable.Version.COMPARATOR).reverse();
|
||||
} else {
|
||||
packages.set(id, toBoardsPackage(platform, installedPlatforms));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const filter = this.typePredicate(options);
|
||||
const boardsPackages = [...packages.values()].filter(filter);
|
||||
const typeFilter = this.typePredicate(options);
|
||||
const searchOutput = resp.getSearchOutputList();
|
||||
const boardsPackages = searchOutput
|
||||
.map((message) => message.toObject(false))
|
||||
.map(createBoardsPackage)
|
||||
.filter(notEmpty)
|
||||
.filter(typeFilter);
|
||||
return sortComponents(boardsPackages, boardsPackageSortGroup);
|
||||
}
|
||||
|
||||
@@ -624,36 +571,48 @@ function boardsPackageSortGroup(boardsPackage: BoardsPackage): SortGroup {
|
||||
return types.join('-') as SortGroup;
|
||||
}
|
||||
|
||||
function toBoardsPackage(
|
||||
platform: Platform,
|
||||
installedPlatforms: Platform[]
|
||||
): BoardsPackage {
|
||||
let installedVersion: string | undefined;
|
||||
const matchingPlatform = installedPlatforms.find(
|
||||
(ip) => ip.getId() === platform.getId()
|
||||
);
|
||||
if (!!matchingPlatform) {
|
||||
installedVersion = matchingPlatform.getInstalled();
|
||||
function createBoardsPackage(
|
||||
summary: PlatformSummary.AsObject
|
||||
): BoardsPackage | undefined {
|
||||
if (!isPlatformSummaryWithMetadata(summary)) {
|
||||
return undefined;
|
||||
}
|
||||
const versionReleaseMap = new Map(summary.releasesMap);
|
||||
const actualRelease =
|
||||
versionReleaseMap.get(summary.installedVersion) ??
|
||||
versionReleaseMap.get(summary.latestVersion);
|
||||
if (!actualRelease) {
|
||||
return undefined;
|
||||
}
|
||||
const { name, typeList, boardsList, deprecated, compatible } = actualRelease;
|
||||
if (!compatible) {
|
||||
return undefined; // never show incompatible platforms
|
||||
}
|
||||
const { id, website, maintainer } = summary.metadata;
|
||||
const availableVersions = Array.from(versionReleaseMap.keys())
|
||||
.sort(Installable.Version.COMPARATOR)
|
||||
.reverse();
|
||||
return {
|
||||
id: platform.getId(),
|
||||
name: platform.getName(),
|
||||
author: platform.getMaintainer(),
|
||||
availableVersions: [platform.getLatest()],
|
||||
description: platform
|
||||
.getBoardsList()
|
||||
.map((b) => b.getName())
|
||||
.join(', '),
|
||||
types: platform.getTypeList(),
|
||||
deprecated: platform.getDeprecated(),
|
||||
id,
|
||||
name,
|
||||
summary: nls.localize(
|
||||
'arduino/component/boardsIncluded',
|
||||
'Boards included in this package:'
|
||||
),
|
||||
installedVersion,
|
||||
boards: platform
|
||||
.getBoardsList()
|
||||
.map((b) => <Board>{ name: b.getName(), fqbn: b.getFqbn() }),
|
||||
moreInfoLink: platform.getWebsite(),
|
||||
description: boardsList.map(({ name }) => name).join(', '),
|
||||
boards: boardsList,
|
||||
types: typeList,
|
||||
moreInfoLink: website,
|
||||
author: maintainer,
|
||||
deprecated,
|
||||
availableVersions,
|
||||
};
|
||||
}
|
||||
|
||||
type PlatformSummaryWithMetadata = PlatformSummary.AsObject &
|
||||
Required<Pick<PlatformSummary.AsObject, 'metadata'>>;
|
||||
function isPlatformSummaryWithMetadata(
|
||||
summary: PlatformSummary.AsObject
|
||||
): summary is PlatformSummaryWithMetadata {
|
||||
return Boolean(summary.metadata);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user