Archived
0
0
Fork 0

feat: add lockfile support

This commit is contained in:
Daryl Ronningen 2022-10-08 12:30:52 -07:00
parent b1bf4ad3fe
commit 177b030ff8
5 changed files with 87 additions and 39 deletions

View file

@ -15,6 +15,7 @@
"commander": "^9.4.1", "commander": "^9.4.1",
"fs-extra": "^10.1.0", "fs-extra": "^10.1.0",
"lowdb": "^3.0.0", "lowdb": "^3.0.0",
"proper-lockfile": "^4.1.2",
"tar": "^6.1.11", "tar": "^6.1.11",
"type-fest": "^3.0.0" "type-fest": "^3.0.0"
}, },
@ -23,6 +24,7 @@
"@rollup/plugin-node-resolve": "^14.1.0", "@rollup/plugin-node-resolve": "^14.1.0",
"@rushstack/eslint-patch": "^1.2.0", "@rushstack/eslint-patch": "^1.2.0",
"@types/fs-extra": "^9.0.13", "@types/fs-extra": "^9.0.13",
"@types/proper-lockfile": "^4.1.2",
"@types/tar": "^6.1.3", "@types/tar": "^6.1.3",
"@typescript-eslint/eslint-plugin": "^5.39.0", "@typescript-eslint/eslint-plugin": "^5.39.0",
"@typescript-eslint/parser": "^5.39.0", "@typescript-eslint/parser": "^5.39.0",

View file

@ -4,10 +4,11 @@ import * as lowdb from 'lowdb';
import crypto from 'node:crypto'; import crypto from 'node:crypto';
import path from 'node:path'; import path from 'node:path';
import os from 'node:os'; import os from 'node:os';
import { lock, unlock } from 'proper-lockfile';
import tar from 'tar'; import tar from 'tar';
import { GlobalOptions } from '../index.js'; import { GlobalOptions } from '../index.js';
import { makeDbFile, parseWahInfo, walk } from '../utils.js'; import { checkLockFile, makeDbFile, parseWahInfo, walk } from '../utils.js';
export default class Install { export default class Install {
public name: string; public name: string;
@ -27,6 +28,9 @@ export default class Install {
} }
await makeDbFile(this.options.sysroot); await makeDbFile(this.options.sysroot);
await checkLockFile(this.options.sysroot);
await lock(`${this.options.sysroot}/var/lib/wahpkg`, { lockfilePath: `${this.options.sysroot}/var/lib/wahpkg.lock` });
if (!await fs.pathExists(path.join(this.options.sysroot, os.tmpdir(), 'wahpkg'))) await fs.mkdirp(path.join(this.options.sysroot, os.tmpdir(), 'wahpkg')); if (!await fs.pathExists(path.join(this.options.sysroot, os.tmpdir(), 'wahpkg'))) await fs.mkdirp(path.join(this.options.sysroot, os.tmpdir(), 'wahpkg'));
const makeExtractDir = await fs.mkdtemp(path.join(this.options.sysroot, os.tmpdir(), 'wahpkg', `${path.basename(this.options.file)}-`)); const makeExtractDir = await fs.mkdtemp(path.join(this.options.sysroot, os.tmpdir(), 'wahpkg', `${path.basename(this.options.file)}-`));
@ -81,6 +85,9 @@ export default class Install {
await fs.rm(path.join(makeExtractDir), { recursive: true, force: true }); await fs.rm(path.join(makeExtractDir), { recursive: true, force: true });
console.log(chalk.bold.green`Package %s has been installed!`, getWahInfo.name); console.log(chalk.bold.green`Package %s has been installed!`, getWahInfo.name);
await unlock(`${this.options.sysroot}/var/lib/wahpkg`, { lockfilePath: `${this.options.sysroot}/var/lib/wahpkg.lock` });
process.exit(0); process.exit(0);
} }
} }

View file

@ -3,9 +3,10 @@ import fs from 'fs-extra';
import * as lowdb from 'lowdb'; import * as lowdb from 'lowdb';
import crypto from 'node:crypto'; import crypto from 'node:crypto';
import path from 'node:path'; import path from 'node:path';
import { lock, unlock } from 'proper-lockfile';
import { GlobalOptions } from '../index.js'; import { GlobalOptions } from '../index.js';
import { makeDbFile } from '../utils.js'; import { checkLockFile, makeDbFile } from '../utils.js';
import { dbData } from './install.js'; import { dbData } from './install.js';
export default class Uninstall { export default class Uninstall {
@ -19,46 +20,50 @@ export default class Uninstall {
public async run(): Promise<void> { public async run(): Promise<void> {
await makeDbFile(this.options.sysroot); await makeDbFile(this.options.sysroot);
await checkLockFile(this.options.sysroot);
if (this.name) { await lock(`${this.options.sysroot}/var/lib/wahpkg`, { lockfilePath: `${this.options.sysroot}/var/lib/wahpkg/wahpkg.lock` });
const dbFile = `${this.options.sysroot}/var/lib/wahpkg/pkgs.json`;
const adapter = new lowdb.JSONFile<dbData>(dbFile);
const db = new lowdb.Low(adapter);
await db.read(); const dbFile = `${this.options.sysroot}/var/lib/wahpkg/pkgs.json`;
const adapter = new lowdb.JSONFile<dbData>(dbFile);
const db = new lowdb.Low(adapter);
if (!db.data.pkgs.find((val) => val.name === this.name)) { await db.read();
console.error(chalk.red.bold`%s is not installed!`, this.name);
process.exit(1);
}
const md5File = await fs.readFile(`${this.options.sysroot}/var/lib/wahpkg/pkgs/${this.name}/MD5HASHES`); if (!db.data.pkgs.find((val) => val.name === this.name)) {
console.error(chalk.red.bold`%s is not installed!`, this.name);
for (const file of md5File.toString().split('\n')) { process.exit(1);
const fileName = file.split(' ')[0];
const hash = file.split(' ')[1];
// Ignore blank or last line
if (fileName === '') continue;
const verifyHash = crypto.createHash('md5').update(await fs.readFile(path.join(this.options.sysroot, fileName))).digest('hex');
if (verifyHash !== hash && this.options['ignore-hash']) {
console.error(chalk.red.bold`%s does not match MD5 hash of %s! To ignore this error, please add --ignore-hash in the command`, this.name, hash);
process.exit(1);
} else {
await fs.rm(path.join(this.options.sysroot, fileName));
}
}
await fs.rm(`${this.options.sysroot}/var/lib/wahpkg/pkgs/${this.name}`, { force: true, recursive: true });
db.data.pkgs = db.data.pkgs.filter((item) => item.name !== this.name);
await db.write();
console.log(chalk.green.bold`%s has been successfully removed!`, this.name);
process.exit(0);
} }
const md5File = await fs.readFile(`${this.options.sysroot}/var/lib/wahpkg/pkgs/${this.name}/MD5HASHES`);
for (const file of md5File.toString().split('\n')) {
const fileName = file.split(' ')[0];
const hash = file.split(' ')[1];
// Ignore blank or last line
if (fileName === '') continue;
const verifyHash = crypto.createHash('md5').update(await fs.readFile(path.join(this.options.sysroot, fileName))).digest('hex');
if (verifyHash !== hash && this.options['ignore-hash']) {
console.error(chalk.red.bold`%s does not match MD5 hash of %s! To ignore this error, please add --ignore-hash in the command`, this.name, hash);
process.exit(1);
} else {
await fs.rm(path.join(this.options.sysroot, fileName));
}
}
await fs.rm(`${this.options.sysroot}/var/lib/wahpkg/pkgs/${this.name}`, { force: true, recursive: true });
db.data.pkgs = db.data.pkgs.filter((item) => item.name !== this.name);
await db.write();
console.log(chalk.green.bold`%s has been successfully removed!`, this.name);
await unlock(`${this.options.sysroot}/var/lib/wahpkg`, { lockfilePath: `${this.options.sysroot}/var/lib/wahpkg/wahpkg.lock` });
process.exit(0);
} }
} }

View file

@ -1,6 +1,7 @@
import chalk from 'chalk'; import chalk from 'chalk';
import fs from 'fs-extra'; import fs from 'fs-extra';
import path from 'node:path'; import path from 'node:path';
import { check, lock } from 'proper-lockfile';
import type { PartialDeep, RequireAllOrNone } from 'type-fest'; import type { PartialDeep, RequireAllOrNone } from 'type-fest';
export function parseWahInfo(file: string): WahInfo { export function parseWahInfo(file: string): WahInfo {
@ -72,6 +73,10 @@ export const makeDbFile = async (sysroot: string): Promise<void> => {
} }
}; };
export const checkLockFile = async (sysroot: string): Promise<boolean> => {
return await check(`${sysroot}/var/lib/wahpkg`, { lockfilePath: `${sysroot}/var/lib/wahpkg/wahpkg.lock` });
};
export interface WahInfo { export interface WahInfo {
name: string; name: string;
version: { version: {

View file

@ -354,6 +354,15 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@types/proper-lockfile@npm:^4.1.2":
version: 4.1.2
resolution: "@types/proper-lockfile@npm:4.1.2"
dependencies:
"@types/retry": "npm:*"
checksum: 0d4f149fac026588f4bb02a888ffff74499ddfdee4d46cf5c59f7abb80200327f696f45a8d77e14211976711a38f0517d526a0da8fe8ded6ba8792d39c9aaceb
languageName: node
linkType: hard
"@types/resolve@npm:1.17.1": "@types/resolve@npm:1.17.1":
version: 1.17.1 version: 1.17.1
resolution: "@types/resolve@npm:1.17.1" resolution: "@types/resolve@npm:1.17.1"
@ -372,6 +381,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@types/retry@npm:*":
version: 0.12.2
resolution: "@types/retry@npm:0.12.2"
checksum: 2534b2da403e94ae5dd5c6967d5b97231fc709fc60d760c41ccfedf9eb93842d160ce913107c1363990524eb6d11c775c8c0236f4d9e83d6e1400d6c443d0f24
languageName: node
linkType: hard
"@types/semver@npm:^7.1.0": "@types/semver@npm:^7.1.0":
version: 7.3.12 version: 7.3.12
resolution: "@types/semver@npm:7.3.12" resolution: "@types/semver@npm:7.3.12"
@ -1618,7 +1634,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6": "graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6":
version: 4.2.10 version: 4.2.10
resolution: "graceful-fs@npm:4.2.10" resolution: "graceful-fs@npm:4.2.10"
checksum: 6b5f9b5aeaee0459b9c37bdbf9624f788703ce291d6bf2d7751f5003942e853f232ca613aec818d1ff7622379bc8b434c635bfda99db93e0b9b8da80ec3d844d checksum: 6b5f9b5aeaee0459b9c37bdbf9624f788703ce291d6bf2d7751f5003942e853f232ca613aec818d1ff7622379bc8b434c635bfda99db93e0b9b8da80ec3d844d
@ -2451,6 +2467,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"proper-lockfile@npm:^4.1.2":
version: 4.1.2
resolution: "proper-lockfile@npm:4.1.2"
dependencies:
graceful-fs: "npm:^4.2.4"
retry: "npm:^0.12.0"
signal-exit: "npm:^3.0.2"
checksum: c015725de952f366e9386330f558b4a7c3089e1db167837840ddd00ac4d1f127ed3d184a5518576ec2cbf514e15d007730d86cf0eea88a810ee0c7bb67345072
languageName: node
linkType: hard
"pump@npm:^3.0.0": "pump@npm:^3.0.0":
version: 3.0.0 version: 3.0.0
resolution: "pump@npm:3.0.0" resolution: "pump@npm:3.0.0"
@ -2709,7 +2736,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"signal-exit@npm:^3.0.7": "signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.7":
version: 3.0.7 version: 3.0.7
resolution: "signal-exit@npm:3.0.7" resolution: "signal-exit@npm:3.0.7"
checksum: 5cf7525c55a72d8d104d914acf2e470f74b2c156197277ad7b331bc5de3d8790170fed3c82ff98c7c31adaa8ff941bfd5ba44f55171cbe8ed0e939fa82a8322a checksum: 5cf7525c55a72d8d104d914acf2e470f74b2c156197277ad7b331bc5de3d8790170fed3c82ff98c7c31adaa8ff941bfd5ba44f55171cbe8ed0e939fa82a8322a
@ -3048,6 +3075,7 @@ __metadata:
"@rollup/plugin-node-resolve": "npm:^14.1.0" "@rollup/plugin-node-resolve": "npm:^14.1.0"
"@rushstack/eslint-patch": "npm:^1.2.0" "@rushstack/eslint-patch": "npm:^1.2.0"
"@types/fs-extra": "npm:^9.0.13" "@types/fs-extra": "npm:^9.0.13"
"@types/proper-lockfile": "npm:^4.1.2"
"@types/tar": "npm:^6.1.3" "@types/tar": "npm:^6.1.3"
"@typescript-eslint/eslint-plugin": "npm:^5.39.0" "@typescript-eslint/eslint-plugin": "npm:^5.39.0"
"@typescript-eslint/parser": "npm:^5.39.0" "@typescript-eslint/parser": "npm:^5.39.0"
@ -3057,6 +3085,7 @@ __metadata:
eslint: "npm:^8.24.0" eslint: "npm:^8.24.0"
fs-extra: "npm:^10.1.0" fs-extra: "npm:^10.1.0"
lowdb: "npm:^3.0.0" lowdb: "npm:^3.0.0"
proper-lockfile: "npm:^4.1.2"
rollup: "npm:^2.79.1" rollup: "npm:^2.79.1"
rollup-plugin-terser: "npm:^7.0.2" rollup-plugin-terser: "npm:^7.0.2"
rollup-plugin-typescript2: "npm:^0.34.1" rollup-plugin-typescript2: "npm:^0.34.1"