diff --git a/src/commands/show-status.ts b/src/commands/show-status.ts new file mode 100644 index 0000000..26b667d --- /dev/null +++ b/src/commands/show-status.ts @@ -0,0 +1,81 @@ +import { Command } from '@oclif/command' +import chalk from 'chalk' + +import { DEVICE_CONFIG_FLAGS, DeviceConfig, getDeviceNames, loadDeviceConfigs } from '../config/device' +import { ImageType, loadBuildIndex } from '../images/build-index' +import { DeviceImage } from '../images/device-image' +import { updateMultiMap } from '../util/data' +import { loadBuildIdToTagMap } from './update-aosp-tag-index' + +export default class ShowStatus extends Command { + static flags = { + ...DEVICE_CONFIG_FLAGS + } + + async run() { + let { flags } = this.parse(ShowStatus) + let configs = await loadDeviceConfigs(flags.devices) + + let buildIdMap = new Map() + // platform security patch levels + let psplMap = new Map() + let imageIndex = await loadBuildIndex() + let presentImages = new Map() + let missingImages = new Map() + let unknownImages = new Map() + let imageTypes = [ImageType.Factory, ImageType.Ota] + + for (let config of configs) { + updateMultiMap(buildIdMap, config.device.build_id, config) + updateMultiMap(psplMap, config.device.platform_security_patch_level_override, config) + + for (let type of imageTypes) { + let image: DeviceImage + try { + image = DeviceImage.get(imageIndex, config, config.device.build_id, type) + } catch { + updateMultiMap(unknownImages, type, config) + continue + } + + if (await image.isPresent()) { + updateMultiMap(presentImages, type, config) + } else { + updateMultiMap(missingImages, type, config) + } + } + } + + let buildIdToTag = await loadBuildIdToTagMap() + + this.log(chalk.bold('Tag | Build ID:')) + for (let [buildId, configs] of buildIdMap.entries()) { + this.log(`${buildIdToTag?.get(buildId) ?? '[no tag]'} | ${buildId}: ` + getDeviceNames(configs)) + } + + if (psplMap.size > 0) { + this.log(chalk.bold('\nPlatform security patch level:')) + for (let [spl, configs] of psplMap.entries()) { + this.log((spl === undefined ? 'default' : spl) + ': ' + getDeviceNames(configs)) + } + } + + this.log(chalk.bold('\nStock image:')) + for (let type of imageTypes) { + this.log(` ${type}:`) + this.maybeLogImageStatus(type, presentImages, 'present') + this.maybeLogImageStatus(type, missingImages, 'known') + this.maybeLogImageStatus(type, unknownImages, chalk.bold(chalk.red('unknown'))) + } + if (unknownImages.size !== 0) { + process.exit(1) + } + } + + maybeLogImageStatus(type: ImageType, map: Map, mapName: string) { + let devices = map.get(type) + if (devices !== undefined && devices.length > 0) { + this.log(` ${mapName}: ${getDeviceNames(devices)}`) + } + } +} diff --git a/src/config/device.ts b/src/config/device.ts index f3e2cba..cf6bf8d 100644 --- a/src/config/device.ts +++ b/src/config/device.ts @@ -231,3 +231,7 @@ async function loadDeviceConfigsFromPath(configPath: string): Promise c.device.name).join(' ') +} diff --git a/src/util/data.ts b/src/util/data.ts index 5891749..4d798c9 100644 --- a/src/util/data.ts +++ b/src/util/data.ts @@ -17,3 +17,12 @@ export function setDifference(a: Set, b: Set) { } return set } + +export function updateMultiMap(map: Map, key: K, value: V) { + let cur = map.get(key) + if (cur === undefined) { + map.set(key, [value]) + } else { + cur.push(value) + } +}