Files
Sanitised 3db508a759 Support for isomorphic-git as an alternative git backend, part 1 (#5229)
* Initial version of git adapter for alternate backend. Only clone is
implemented.

* Regenerate package-lock.json

* Clarify comments in config.yaml regarding git backend options

---------

Co-authored-by: Sanitised <sanitised@users.noreply.github.com>
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
2026-03-01 17:08:07 +02:00

98 lines
3.4 KiB
JavaScript

// Plugin manager script.
// Usage:
// 1. node plugins.js update
// 2. node plugins.js install <plugin-git-url>
// More operations coming soon.
import fs from 'node:fs';
import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import { default as git, CheckRepoActions } from 'simple-git';
import { createGitClient } from './src/git/client.js';
import { color } from './src/util.js';
const __dirname = import.meta.dirname ?? path.dirname(fileURLToPath(import.meta.url));
process.chdir(__dirname);
const pluginsPath = './plugins';
const gitBackend = process.env.SILLYTAVERN_GIT_BACKEND || 'auto';
const command = process.argv[2];
if (!command) {
console.log('Usage: node plugins.js <command>');
console.log('Commands:');
console.log(' update - Update all installed plugins');
console.log(' install <plugin-git-url> - Install plugin from a Git URL');
process.exit(1);
}
if (command === 'update') {
console.log(color.magenta('Updating all plugins'));
updatePlugins();
}
if (command === 'install') {
const pluginName = process.argv[3];
console.log('Installing a new plugin', color.green(pluginName));
installPlugin(pluginName);
}
async function updatePlugins() {
const directories = fs.readdirSync(pluginsPath)
.filter(file => !file.startsWith('.'))
.filter(file => fs.statSync(path.join(pluginsPath, file)).isDirectory());
console.log(`Found ${color.cyan(directories.length)} directories in ./plugins`);
for (const directory of directories) {
try {
console.log(`Updating plugin ${color.green(directory)}...`);
const pluginPath = path.join(pluginsPath, directory);
const pluginRepo = git(pluginPath);
const isRepo = await pluginRepo.checkIsRepo(CheckRepoActions.IS_REPO_ROOT);
if (!isRepo) {
console.log(`Directory ${color.yellow(directory)} is not a Git repository`);
continue;
}
await pluginRepo.fetch();
const commitHash = await pluginRepo.revparse(['HEAD']);
const trackingBranch = await pluginRepo.revparse(['--abbrev-ref', '@{u}']);
const log = await pluginRepo.log({
from: commitHash,
to: trackingBranch,
});
if (log.total === 0) {
console.log(`Plugin ${color.blue(directory)} is already up to date`);
continue;
}
await pluginRepo.pull();
const latestCommit = await pluginRepo.revparse(['HEAD']);
console.log(`Plugin ${color.green(directory)} updated to commit ${color.cyan(latestCommit)}`);
} catch (error) {
console.error(color.red(`Failed to update plugin ${directory}: ${error.message}`));
}
}
console.log(color.magenta('All plugins updated!'));
}
async function installPlugin(pluginName) {
try {
const pluginPath = path.join(pluginsPath, path.basename(pluginName, '.git'));
if (fs.existsSync(pluginPath)) {
return console.log(color.yellow(`Directory already exists at ${pluginPath}`));
}
await createGitClient({ backend: gitBackend }).clone(pluginName, pluginPath, { depth: 1 });
console.log(`Plugin ${color.green(pluginName)} installed to ${color.cyan(pluginPath)}`);
} catch (error) {
console.error(color.red(`Failed to install plugin ${pluginName}`), error);
}
}