corepack/sources/commands/Hydrate.ts

65 lines
2.2 KiB
TypeScript

import {Command, UsageError} from 'clipanion';
import path from 'path';
import tar from 'tar';
import * as folderUtils from '../folderUtils';
import {Context} from '../main';
import {SupportedPackageManagerSet, SupportedPackageManagers} from '../types';
export class HydrateCommand extends Command<Context> {
static usage = Command.Usage({
description: `Import a package manager into the cache`,
details: `
This command unpacks a package manager archive into the cache. The archive must have been generated by the \`corepack pack\` command - no other will work.
`,
examples: [[
`Import a package manager in the cache`,
`$0 hydrate corepack-yarn-2.2.2.tgz`,
]],
});
@Command.String()
fileName!: string;
@Command.Boolean(`--activate`)
activate: boolean = false;
@Command.Path(`hydrate`)
async execute() {
const installFolder = folderUtils.getInstallFolder();
const fileName = path.resolve(this.context.cwd, this.fileName);
const firstLevel = new Set();
const secondLevel = new Set();
let hasShortEntries = false;
await tar.t({file: fileName, onentry: entry => {
const segments = entry.header.path.split(/\//g);
if (segments.length < 3) {
hasShortEntries = true;
} else {
firstLevel.add(segments[0]);
secondLevel.add(segments[1]);
}
}});
if (hasShortEntries || firstLevel.size !== 1 || secondLevel.size !== 1)
throw new UsageError(`Invalid archive format; did it get generated by 'corepack prepare'?`);
const name = [...firstLevel][0] as SupportedPackageManagers;
const reference = [...secondLevel][0] as string;
if (!SupportedPackageManagerSet.has(name))
throw new UsageError(`Unsupported package manager '${name}'`);
await tar.x({file: fileName, cwd: installFolder});
if (this.activate)
await this.context.engine.activatePackageManager({name, reference});
this.context.stdout.write(`Hydrated ${name}@${reference}\n`);
}
}