mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-19 22:23:33 +01:00
04063d664b
* fix bin folder and workflows as far its possible cleanup of dockerfile changed paths of scripts add lock file fix working directory for workflows fix windows bin fix travis (is travis used anyway?) fix package refs remove pnpm-lock file in root as these conflicts with the docker volume setup optimize comments use install again refactor prod image call to run fix --workspace can only be used inside a workspace correct comment try fix pipeline try fix pipeline for upgrade-from-latest-release install all deps smaller adjustments save update dockerfile remove workspace command fix run test command start repair latest release workflow start repair latest release workflow start repair latest release workflow further repairs * remove test plugin from docker compose
84 lines
3.2 KiB
JavaScript
84 lines
3.2 KiB
JavaScript
'use strict';
|
|
|
|
/*
|
|
This is a repair tool. It rebuilds an old pad at a new pad location up to a
|
|
known "good" revision.
|
|
*/
|
|
|
|
// As of v14, Node.js does not exit when there is an unhandled Promise rejection. Convert an
|
|
// unhandled rejection into an uncaught exception, which does cause Node.js to exit.
|
|
process.on('unhandledRejection', (err) => { throw err; });
|
|
|
|
if (process.argv.length !== 4 && process.argv.length !== 5) {
|
|
throw new Error('Use: node bin/repairPad.js $PADID $REV [$NEWPADID]');
|
|
}
|
|
|
|
const padId = process.argv[2];
|
|
const newRevHead = process.argv[3];
|
|
const newPadId = process.argv[4] || `${padId}-rebuilt`;
|
|
|
|
(async () => {
|
|
const db = require('./src/node/db/DB');
|
|
await db.init();
|
|
|
|
const PadManager = require('./src/node/db/PadManager');
|
|
const Pad = require('./src/node/db/Pad').Pad;
|
|
// Validate the newPadId if specified and that a pad with that ID does
|
|
// not already exist to avoid overwriting it.
|
|
if (!PadManager.isValidPadId(newPadId)) {
|
|
throw new Error('Cannot create a pad with that id as it is invalid');
|
|
}
|
|
const exists = await PadManager.doesPadExist(newPadId);
|
|
if (exists) throw new Error('Cannot create a pad with that id as it already exists');
|
|
|
|
const oldPad = await PadManager.getPad(padId);
|
|
const newPad = new Pad(newPadId);
|
|
|
|
// Clone all Chat revisions
|
|
const chatHead = oldPad.chatHead;
|
|
await Promise.all([...Array(chatHead + 1).keys()].map(async (i) => {
|
|
const chat = await db.get(`pad:${padId}:chat:${i}`);
|
|
await db.set(`pad:${newPadId}:chat:${i}`, chat);
|
|
console.log(`Created: Chat Revision: pad:${newPadId}:chat:${i}`);
|
|
}));
|
|
|
|
// Rebuild Pad from revisions up to and including the new revision head
|
|
const AuthorManager = require('./src/node/db/AuthorManager');
|
|
const Changeset = require('./src/static/js/Changeset');
|
|
// Author attributes are derived from changesets, but there can also be
|
|
// non-author attributes with specific mappings that changesets depend on
|
|
// and, AFAICT, cannot be recreated any other way
|
|
newPad.pool.numToAttrib = oldPad.pool.numToAttrib;
|
|
for (let curRevNum = 0; curRevNum <= newRevHead; curRevNum++) {
|
|
const rev = await db.get(`pad:${padId}:revs:${curRevNum}`);
|
|
if (!rev || !rev.meta) throw new Error('The specified revision number could not be found.');
|
|
const newRevNum = ++newPad.head;
|
|
const newRevId = `pad:${newPad.id}:revs:${newRevNum}`;
|
|
await Promise.all([
|
|
db.set(newRevId, rev),
|
|
AuthorManager.addPad(rev.meta.author, newPad.id),
|
|
]);
|
|
newPad.atext = Changeset.applyToAText(rev.changeset, newPad.atext, newPad.pool);
|
|
console.log(`Created: Revision: pad:${newPad.id}:revs:${newRevNum}`);
|
|
}
|
|
|
|
// Add saved revisions up to the new revision head
|
|
console.log(newPad.head);
|
|
const newSavedRevisions = [];
|
|
for (const savedRev of oldPad.savedRevisions) {
|
|
if (savedRev.revNum <= newRevHead) {
|
|
newSavedRevisions.push(savedRev);
|
|
console.log(`Added: Saved Revision: ${savedRev.revNum}`);
|
|
}
|
|
}
|
|
newPad.savedRevisions = newSavedRevisions;
|
|
|
|
// Save the source pad
|
|
await db.set(`pad:${newPadId}`, newPad);
|
|
|
|
console.log(`Created: Source Pad: pad:${newPadId}`);
|
|
await newPad.saveToDatabase();
|
|
|
|
await db.shutdown();
|
|
console.info('finished');
|
|
})();
|