2022-12-21 13:17:50 +00:00
|
|
|
const Myt = require('./myt');
|
2022-12-21 12:34:17 +00:00
|
|
|
const Command = require('./lib/command');
|
2022-05-08 20:44:40 +00:00
|
|
|
const fs = require('fs-extra');
|
2023-01-25 17:16:43 +00:00
|
|
|
const path = require('path');
|
2022-05-08 20:44:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Cleans old applied versions.
|
|
|
|
*/
|
2022-12-21 12:34:17 +00:00
|
|
|
class Clean extends Command {
|
|
|
|
static usage = {
|
2024-01-17 14:14:35 +00:00
|
|
|
description: 'Cleans old applied versions',
|
|
|
|
params: {
|
2024-09-04 12:50:27 +00:00
|
|
|
purge: 'Whether to remove non-existent scripts from DB log'
|
2024-01-17 14:14:35 +00:00
|
|
|
}
|
2022-12-21 12:34:17 +00:00
|
|
|
};
|
|
|
|
|
2022-12-29 09:15:02 +00:00
|
|
|
static opts = {
|
2024-01-17 14:14:35 +00:00
|
|
|
alias: {
|
|
|
|
purge: 'p'
|
|
|
|
},
|
|
|
|
boolean: [
|
|
|
|
'purge'
|
|
|
|
],
|
2022-12-21 12:34:17 +00:00
|
|
|
default: {
|
|
|
|
remote: 'production'
|
|
|
|
}
|
|
|
|
};
|
2022-05-08 20:44:40 +00:00
|
|
|
|
2024-01-04 12:02:40 +00:00
|
|
|
static reporter = {
|
2024-01-19 10:50:24 +00:00
|
|
|
versionsArchived: function(nVersions) {
|
|
|
|
if (nVersions)
|
2024-01-22 16:28:47 +00:00
|
|
|
console.log(` -> ${nVersions} versions archived.`);
|
2024-01-19 10:50:24 +00:00
|
|
|
else
|
|
|
|
console.log(` -> No versions archived.`);
|
2024-01-04 12:02:40 +00:00
|
|
|
},
|
2024-01-19 10:50:24 +00:00
|
|
|
versionLogPurged: function(nPurged) {
|
|
|
|
if (nPurged)
|
|
|
|
console.log(` -> ${nPurged} changes purged from log.`);
|
|
|
|
else
|
|
|
|
console.log(` -> No logs purged.`);
|
|
|
|
}
|
2024-01-04 12:02:40 +00:00
|
|
|
};
|
|
|
|
|
2022-12-21 13:17:50 +00:00
|
|
|
async run(myt, opts) {
|
2024-01-17 14:14:35 +00:00
|
|
|
const conn = await myt.dbConnect();
|
|
|
|
const archiveDir = path.join(opts.versionsDir, '.archive');
|
|
|
|
|
2024-01-14 14:49:49 +00:00
|
|
|
const dbVersion = await myt.fetchDbVersion() || {};
|
|
|
|
const number = parseInt(dbVersion.number);
|
2022-05-08 20:44:40 +00:00
|
|
|
|
|
|
|
const oldVersions = [];
|
2022-12-21 12:34:17 +00:00
|
|
|
const versionDirs = await fs.readdir(opts.versionsDir);
|
2022-05-08 20:44:40 +00:00
|
|
|
for (const versionDir of versionDirs) {
|
2024-01-14 14:49:49 +00:00
|
|
|
const version = await myt.loadVersion(versionDir);
|
|
|
|
const shouldArchive = version
|
|
|
|
&& !version.apply
|
|
|
|
&& parseInt(version.number) < number;
|
2022-05-08 20:44:40 +00:00
|
|
|
|
2024-01-14 14:49:49 +00:00
|
|
|
if (shouldArchive)
|
2022-05-08 20:44:40 +00:00
|
|
|
oldVersions.push(versionDir);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opts.maxOldVersions
|
|
|
|
&& oldVersions.length > opts.maxOldVersions) {
|
|
|
|
oldVersions.splice(-opts.maxOldVersions);
|
|
|
|
|
2023-01-25 17:16:43 +00:00
|
|
|
if (!await fs.pathExists(archiveDir))
|
|
|
|
await fs.mkdir(archiveDir);
|
|
|
|
|
2024-01-17 16:53:48 +00:00
|
|
|
for (const oldVersion of oldVersions) {
|
|
|
|
const srcDir = path.join(opts.versionsDir, oldVersion);
|
|
|
|
const dstDir = path.join(archiveDir, oldVersion);
|
|
|
|
|
|
|
|
if (!await fs.pathExists(dstDir))
|
|
|
|
await fs.mkdir(dstDir);
|
|
|
|
|
|
|
|
const scripts = await fs.readdir(srcDir);
|
|
|
|
for (const script of scripts) {
|
|
|
|
await fs.move(
|
|
|
|
path.join(srcDir, script),
|
|
|
|
path.join(dstDir, script),
|
|
|
|
{overwrite: true}
|
|
|
|
);
|
|
|
|
}
|
2022-05-08 20:44:40 +00:00
|
|
|
|
2024-01-17 16:53:48 +00:00
|
|
|
await fs.rmdir(srcDir);
|
|
|
|
}
|
2022-05-08 20:44:40 +00:00
|
|
|
|
2024-01-19 10:50:24 +00:00
|
|
|
this.emit('versionsArchived', oldVersions.length);
|
2022-05-08 20:44:40 +00:00
|
|
|
} else
|
2024-01-19 10:50:24 +00:00
|
|
|
this.emit('versionsArchived');
|
2024-01-17 14:14:35 +00:00
|
|
|
|
|
|
|
if (opts.purge) {
|
|
|
|
const versionDb = new VersionDb(myt, opts.versionsDir);
|
|
|
|
versionDb.load();
|
|
|
|
|
|
|
|
const archiveDb = new VersionDb(myt, archiveDir);
|
|
|
|
archiveDb.load();
|
|
|
|
|
|
|
|
const [res] = await conn.query(
|
|
|
|
`SELECT number, file FROM versionLog
|
|
|
|
WHERE code = ?
|
|
|
|
ORDER BY number, file`,
|
|
|
|
[opts.code]
|
|
|
|
);
|
|
|
|
|
2024-01-19 09:16:47 +00:00
|
|
|
let nPurged = 0;
|
2024-01-17 14:14:35 +00:00
|
|
|
for (const script of res) {
|
|
|
|
const hasVersion = await versionDb.hasScript(script);
|
|
|
|
const hasArchive = await archiveDb.hasScript(script);
|
|
|
|
|
|
|
|
if (!hasVersion && !hasArchive) {
|
|
|
|
await conn.query(
|
|
|
|
`DELETE FROM versionLog
|
|
|
|
WHERE code = ? AND number = ? AND file = ?`,
|
|
|
|
[opts.code, script.number, script.file]
|
|
|
|
);
|
2024-01-19 09:16:47 +00:00
|
|
|
nPurged++;
|
2024-01-17 14:14:35 +00:00
|
|
|
}
|
|
|
|
}
|
2024-01-19 10:50:24 +00:00
|
|
|
|
|
|
|
this.emit('versionLogPurged', nPurged);
|
2024-01-17 14:14:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class VersionDb {
|
|
|
|
constructor(myt, baseDir) {
|
|
|
|
Object.assign(this, {myt, baseDir});
|
|
|
|
}
|
|
|
|
|
|
|
|
async load() {
|
2024-01-19 09:16:47 +00:00
|
|
|
const map = this.map = new Map();
|
2024-01-17 14:14:35 +00:00
|
|
|
if (await fs.pathExists(this.baseDir)) {
|
|
|
|
const dirs = await fs.readdir(this.baseDir);
|
|
|
|
for (const dir of dirs) {
|
|
|
|
const version = this.myt.parseVersionDir(dir);
|
|
|
|
if (!version) continue;
|
2024-01-19 09:16:47 +00:00
|
|
|
let subdirs = map.get(version.number);
|
|
|
|
if (!subdirs) map.set(version.number, subdirs = []);
|
|
|
|
subdirs.push(dir);
|
2024-01-17 14:14:35 +00:00
|
|
|
}
|
|
|
|
}
|
2024-01-19 09:16:47 +00:00
|
|
|
return map;
|
2024-01-17 14:14:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async hasScript(script) {
|
2024-01-19 09:16:47 +00:00
|
|
|
const dirs = this.map.get(script.number);
|
|
|
|
if (dirs)
|
|
|
|
for (const dir of dirs) {
|
|
|
|
const scriptPath = path.join(this.baseDir, dir, script.file);
|
|
|
|
if (await fs.pathExists(scriptPath)) return true;
|
|
|
|
}
|
|
|
|
return false;
|
2022-05-08 20:44:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = Clean;
|
|
|
|
|
|
|
|
if (require.main === module)
|
2024-01-04 12:02:40 +00:00
|
|
|
new Myt().cli(Clean);
|