UNPKG

xpm

Version:

The xPack project manager command line tool

221 lines (175 loc) 6.3 kB
/* * This file is part of the xPack project (http://xpack.github.io). * Copyright (c) 2020-2026 Liviu Ionescu. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software * for any purpose is hereby granted, under the terms of the MIT license. * * If a copy of the license was not distributed with this file, it can * be obtained from https://opensource.org/license/mit. */ 'use strict' // ---------------------------------------------------------------------------- /** * The `xpm binaries-update ...` command implementation. */ // ---------------------------------------------------------------------------- // https://nodejs.org/docs/latest/api/ import fs from 'fs/promises' import path from 'path' import util from 'util' // ---------------------------------------------------------------------------- // import { CliCommand, CliError, CliErrorInput, // CliExitCodes } from '@ilg/cli-start-options' import cliStartOptionsCsj from '@ilg/cli-start-options' // https://www.npmjs.com/package/@xpack/xpm-lib import * as xpmLib from '@xpack/xpm-lib' // ---------------------------------------------------------------------------- import { GlobalConfig } from '../classes/global-config.js' // ---------------------------------------------------------------------------- const { CliCommand, CliError, CliErrorInput, CliExitCodes } = cliStartOptionsCsj // ============================================================================ export class BinariesUpdate extends CliCommand { // -------------------------------------------------------------------------- /** * @summary Constructor, to set help definitions. * * @param {Object} context Reference to a context. */ constructor(context) { super(context) // Title displayed with the help message. this.title = 'xPack project manager - update binaries' this.optionGroups = [ { title: 'Update binaries options', postOptions: '<version> <folder>', // Extra arguments. optionDefs: [], }, ] } /** * @summary Execute the `binaries-update` command. * * @param {string[]} args Command line arguments. * @returns {number} Return code. * * @override */ async doRun(args) { const log = this.log log.trace(`${this.constructor.name}.doRun()`) log.info(this.title) log.info() const context = this.context const config = context.config context.globalConfig = new GlobalConfig() const xpmPackage = new xpmLib.Package({ log, packageFolderPath: config.cwd, }) try { // Read `package.json`; throw if not valid. this.jsonPackage = await xpmPackage.readPackageDotJson({ withThrow: true, }) } catch (error) { throw new CliErrorInput(error.message) } if (!xpmPackage.isXpmPackage()) { throw new CliErrorInput( 'current folder is not an xpm package, ' + 'check for the "xpack" property in package.json' ) } if (args.length !== 2) { throw new CliError( 'this command requires two arguments', CliExitCodes.ERROR.SYNTAX ) } const version = args[0] const fromFolderPath = await fs.realpath(args[1]) // Follow the link and check the destination. let stats try { stats = await fs.stat(fromFolderPath) } catch { throw new CliErrorInput(`'${fromFolderPath}' does not exist`) } if (!stats.isDirectory()) { throw new CliErrorInput(`'${fromFolderPath}' is not a folder`) } log.verbose(`Scanning '${fromFolderPath}' for .sha files...`) const archiveNames = {} const fileNames = await fs.readdir(fromFolderPath) for (const fileName of fileNames) { log.trace(`File name: ${fileName}`) if (!fileName.includes(version)) { log.warn(`'${fileName}' is not version '${version}, ignored`) continue } if (fileName.endsWith('.sha')) { const filePath = path.join(fromFolderPath, fileName) log.verbose(`Parsing file: ${filePath}...`) const fileContent = await fs.readFile(filePath, { encoding: 'ascii', }) const lines = fileContent.split('\n') for (const line of lines) { if (line.trim().length) { log.trace(`Line from file: ${line}`) const words = line.split(' ') archiveNames[words[1]] = words[0] } } } } const jsonBinaries = this.jsonPackage.xpack.binaries log.info('Processing entries...') for (const [key, value] of Object.entries(archiveNames)) { if (key === '.DS_Store') { continue } log.info(`- ${key}`) const parts = key.split('-') log.trace(parts) const filePlatform = parts[parts.length - 2] const fileArchitecture = parts[parts.length - 1].split('.')[0] log.trace(filePlatform, fileArchitecture) let jsonPlatformName = `${filePlatform}-${fileArchitecture}` let jsonPlatform = jsonBinaries.platforms[jsonPlatformName] if (!jsonPlatform && fileArchitecture === 'ia32') { jsonPlatformName = `${filePlatform}-x86` jsonPlatform = jsonBinaries.platforms[jsonPlatformName] } if (!jsonPlatform) { log.warn(`${filePlatform}-${fileArchitecture} not found, ignored`) } else { if (jsonPlatformName.endsWith('x86')) { log.warn( `Platform '${jsonPlatformName}' deprecated, ` + `use '${filePlatform}-${fileArchitecture}'` ) } jsonBinaries.platforms[jsonPlatformName] = { fileName: key, sha256: value, } } } // Do not add the terminating '/'! const baseUrl = jsonBinaries.baseUrl.replace(/\/v[0-9].*$/, `/v${version}`) jsonBinaries.baseUrl = baseUrl log.info() log.info(`URL: '${baseUrl}'`) log.trace(util.inspect(jsonBinaries)) await xpmPackage.rewritePackageDotJson(this.jsonPackage) if (log.isVerbose) { this.outputDoneDuration() } return CliExitCodes.SUCCESS } // -------------------------------------------------------------------------- } // ----------------------------------------------------------------------------