mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Merge pull request #3933 from SillyTavern/feat/ext-installer-branch
Add branch selection on extension installer
This commit is contained in:
@@ -1120,7 +1120,7 @@ export function initRossMods() {
|
||||
const result = await Popup.show.confirm('Regenerate Message', 'Are you sure you want to regenerate the latest message?', {
|
||||
customInputs: [{ id: 'regenerateWithCtrlEnter', label: 'Don\'t ask again' }],
|
||||
onClose: (popup) => {
|
||||
regenerateWithCtrlEnter = popup.inputResults.get('regenerateWithCtrlEnter') ?? false;
|
||||
regenerateWithCtrlEnter = Boolean(popup.inputResults.get('regenerateWithCtrlEnter') ?? false);
|
||||
},
|
||||
});
|
||||
if (!result) {
|
||||
|
@@ -661,6 +661,7 @@ function generateExtensionHtml(name, manifest, isActive, isDisabled, isExternal,
|
||||
let deleteButton = isExternal ? `<button class="btn_delete menu_button" data-name="${externalId}" data-i18n="[title]Delete" title="Delete"><i class="fa-fw fa-solid fa-trash-can"></i></button>` : '';
|
||||
let updateButton = isExternal ? `<button class="btn_update menu_button displayNone" data-name="${externalId}" title="Update available"><i class="fa-solid fa-download fa-fw"></i></button>` : '';
|
||||
let moveButton = isExternal && isUserAdmin ? `<button class="btn_move menu_button" data-name="${externalId}" data-i18n="[title]Move" title="Move"><i class="fa-solid fa-folder-tree fa-fw"></i></button>` : '';
|
||||
let branchButton = isExternal && isUserAdmin ? `<button class="btn_branch menu_button" data-name="${externalId}" data-i18n="[title]Switch branch" title="Switch branch"><i class="fa-solid fa-code-branch fa-fw"></i></button>` : '';
|
||||
let modulesInfo = '';
|
||||
|
||||
if (isActive && Array.isArray(manifest.optional)) {
|
||||
@@ -701,6 +702,7 @@ function generateExtensionHtml(name, manifest, isActive, isDisabled, isExternal,
|
||||
|
||||
<div class="extension_actions flex-container alignItemsCenter">
|
||||
${updateButton}
|
||||
${branchButton}
|
||||
${moveButton}
|
||||
${deleteButton}
|
||||
</div>
|
||||
@@ -944,6 +946,44 @@ async function onDeleteClick() {
|
||||
}
|
||||
}
|
||||
|
||||
async function onBranchClick() {
|
||||
const extensionName = $(this).data('name');
|
||||
const isCurrentUserAdmin = isAdmin();
|
||||
const isGlobal = getExtensionType(extensionName) === 'global';
|
||||
if (isGlobal && !isCurrentUserAdmin) {
|
||||
toastr.error(t`You don't have permission to switch branch.`);
|
||||
return;
|
||||
}
|
||||
|
||||
let newBranch = '';
|
||||
|
||||
const branches = await getExtensionBranches(extensionName, isGlobal);
|
||||
const selectElement = document.createElement('select');
|
||||
selectElement.classList.add('text_pole', 'wide100p');
|
||||
selectElement.addEventListener('change', function () {
|
||||
newBranch = this.value;
|
||||
});
|
||||
for (const branch of branches) {
|
||||
const option = document.createElement('option');
|
||||
option.value = branch.name;
|
||||
option.textContent = `${branch.name} (${branch.commit}) [${branch.label}]`;
|
||||
option.selected = branch.current;
|
||||
selectElement.appendChild(option);
|
||||
}
|
||||
|
||||
const popup = new Popup(selectElement, POPUP_TYPE.CONFIRM, '', {
|
||||
okButton: t`Switch`,
|
||||
cancelButton: t`Cancel`,
|
||||
});
|
||||
const popupResult = await popup.show();
|
||||
|
||||
if (!popupResult || !newBranch) {
|
||||
return;
|
||||
}
|
||||
|
||||
await switchExtensionBranch(extensionName, isGlobal, newBranch);
|
||||
}
|
||||
|
||||
async function onMoveClick() {
|
||||
const extensionName = $(this).data('name');
|
||||
const isCurrentUserAdmin = isAdmin();
|
||||
@@ -1055,13 +1095,83 @@ async function getExtensionVersion(extensionName, abortSignal) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of branches for a specific extension.
|
||||
* @param {string} extensionName The name of the extension
|
||||
* @param {boolean} isGlobal Whether the extension is global or not
|
||||
* @returns {Promise<ExtensionBranch[]>} List of branches for the extension
|
||||
* @typedef {object} ExtensionBranch
|
||||
* @property {string} name The name of the branch
|
||||
* @property {string} commit The commit hash of the branch
|
||||
* @property {boolean} current Whether this branch is the current one
|
||||
* @property {string} label The commit label of the branch
|
||||
*/
|
||||
async function getExtensionBranches(extensionName, isGlobal) {
|
||||
try {
|
||||
const response = await fetch('/api/extensions/branches', {
|
||||
method: 'POST',
|
||||
headers: getRequestHeaders(),
|
||||
body: JSON.stringify({
|
||||
extensionName,
|
||||
global: isGlobal,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const text = await response.text();
|
||||
toastr.error(text || response.statusText, t`Extension branches fetch failed`);
|
||||
console.error('Extension branches fetch failed', response.status, response.statusText, text);
|
||||
return [];
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches the branch of an extension.
|
||||
* @param {string} extensionName The name of the extension
|
||||
* @param {boolean} isGlobal If the extension is global
|
||||
* @param {string} branch Branch name to switch to
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function switchExtensionBranch(extensionName, isGlobal, branch) {
|
||||
try {
|
||||
const response = await fetch('/api/extensions/switch', {
|
||||
method: 'POST',
|
||||
headers: getRequestHeaders(),
|
||||
body: JSON.stringify({
|
||||
extensionName,
|
||||
branch,
|
||||
global: isGlobal,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const text = await response.text();
|
||||
toastr.error(text || response.statusText, t`Extension branch switch failed`);
|
||||
console.error('Extension branch switch failed', response.status, response.statusText, text);
|
||||
return;
|
||||
}
|
||||
|
||||
toastr.success(t`Extension ${extensionName} switched to ${branch}`);
|
||||
await loadExtensionSettings({}, false, false);
|
||||
void showExtensionsDetails();
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs a third-party extension via the API.
|
||||
* @param {string} url Extension repository URL
|
||||
* @param {boolean} global Is the extension global?
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function installExtension(url, global) {
|
||||
export async function installExtension(url, global, branch = '') {
|
||||
console.debug('Extension installation started', url);
|
||||
|
||||
toastr.info(t`Please wait...`, t`Installing extension`);
|
||||
@@ -1072,6 +1182,7 @@ export async function installExtension(url, global) {
|
||||
body: JSON.stringify({
|
||||
url,
|
||||
global,
|
||||
branch,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -1406,9 +1517,17 @@ export async function openThirdPartyExtensionMenu(suggestUrl = '') {
|
||||
await popup.complete(POPUP_RESULT.AFFIRMATIVE);
|
||||
},
|
||||
};
|
||||
/** @type {import('./popup.js').CustomPopupInput} */
|
||||
const branchNameInput = {
|
||||
id: 'extension_branch_name',
|
||||
label: t`Branch or tag name (optional)`,
|
||||
type: 'text',
|
||||
tooltip: 'e.g. main, dev, v1.0.0',
|
||||
};
|
||||
|
||||
const customButtons = isCurrentUserAdmin ? [installForAllButton] : [];
|
||||
const popup = new Popup(html, POPUP_TYPE.INPUT, suggestUrl ?? '', { okButton, customButtons });
|
||||
const customInputs = [branchNameInput];
|
||||
const popup = new Popup(html, POPUP_TYPE.INPUT, suggestUrl ?? '', { okButton, customButtons, customInputs });
|
||||
const input = await popup.show();
|
||||
|
||||
if (!input) {
|
||||
@@ -1417,7 +1536,8 @@ export async function openThirdPartyExtensionMenu(suggestUrl = '') {
|
||||
}
|
||||
|
||||
const url = String(input).trim();
|
||||
await installExtension(url, global);
|
||||
const branchName = String(popup.inputResults.get('extension_branch_name') ?? '').trim();
|
||||
await installExtension(url, global, branchName);
|
||||
}
|
||||
|
||||
export async function initExtensions() {
|
||||
@@ -1433,6 +1553,7 @@ export async function initExtensions() {
|
||||
$(document).on('click', '.extensions_info .extension_block .btn_update', onUpdateClick);
|
||||
$(document).on('click', '.extensions_info .extension_block .btn_delete', onDeleteClick);
|
||||
$(document).on('click', '.extensions_info .extension_block .btn_move', onMoveClick);
|
||||
$(document).on('click', '.extensions_info .extension_block .btn_branch', onBranchClick);
|
||||
|
||||
/**
|
||||
* Handles the click event for the third-party extension import button.
|
||||
|
@@ -291,7 +291,7 @@ async function installAsset(url, assetType, filename) {
|
||||
try {
|
||||
if (category === 'extension') {
|
||||
console.debug(DEBUG_PREFIX, 'Installing extension ', url);
|
||||
await installExtension(url);
|
||||
await installExtension(url, false);
|
||||
console.debug(DEBUG_PREFIX, 'Extension installed.');
|
||||
return;
|
||||
}
|
||||
@@ -309,7 +309,7 @@ async function installAsset(url, assetType, filename) {
|
||||
console.debug(DEBUG_PREFIX, 'Importing character ', filename);
|
||||
const blob = await result.blob();
|
||||
const file = new File([blob], filename, { type: blob.type });
|
||||
await processDroppedFiles([file], true);
|
||||
await processDroppedFiles([file]);
|
||||
console.debug(DEBUG_PREFIX, 'Character downloaded.');
|
||||
}
|
||||
}
|
||||
|
@@ -71,7 +71,8 @@ export const POPUP_RESULT = {
|
||||
* @property {string} id - The id for the html element
|
||||
* @property {string} label - The label text for the input
|
||||
* @property {string?} [tooltip=null] - Optional tooltip icon displayed behind the label
|
||||
* @property {boolean?} [defaultState=false] - The default state when opening the popup (false if not set)
|
||||
* @property {boolean|string|undefined} [defaultState=false] - The default state when opening the popup (false if not set)
|
||||
* @property {string?} [type='checkbox'] - The type of the input (default is checkbox)
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -157,7 +158,7 @@ export class Popup {
|
||||
|
||||
/** @type {POPUP_RESULT|number} */ result;
|
||||
/** @type {any} */ value;
|
||||
/** @type {Map<string,boolean>?} */ inputResults;
|
||||
/** @type {Map<string,string|boolean>?} */ inputResults;
|
||||
/** @type {any} */ cropData;
|
||||
|
||||
/** @type {HTMLElement} */ lastFocus;
|
||||
@@ -260,13 +261,14 @@ export class Popup {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!input.type || input.type === 'checkbox') {
|
||||
const label = document.createElement('label');
|
||||
label.classList.add('checkbox_label', 'justifyCenter');
|
||||
label.setAttribute('for', input.id);
|
||||
const inputElement = document.createElement('input');
|
||||
inputElement.type = 'checkbox';
|
||||
inputElement.id = input.id;
|
||||
inputElement.checked = input.defaultState ?? false;
|
||||
inputElement.checked = Boolean(input.defaultState ?? false);
|
||||
label.appendChild(inputElement);
|
||||
const labelText = document.createElement('span');
|
||||
labelText.innerText = input.label;
|
||||
@@ -282,6 +284,30 @@ export class Popup {
|
||||
}
|
||||
|
||||
this.inputControls.appendChild(label);
|
||||
} else if (input.type === 'text') {
|
||||
const label = document.createElement('label');
|
||||
label.classList.add('text_label', 'justifyCenter');
|
||||
label.setAttribute('for', input.id);
|
||||
|
||||
const inputElement = document.createElement('input');
|
||||
inputElement.classList.add('text_pole');
|
||||
inputElement.type = 'text';
|
||||
inputElement.id = input.id;
|
||||
inputElement.value = String(input.defaultState ?? '');
|
||||
inputElement.placeholder = input.tooltip ?? '';
|
||||
|
||||
const labelText = document.createElement('span');
|
||||
labelText.innerText = input.label;
|
||||
labelText.dataset.i18n = input.label;
|
||||
|
||||
label.appendChild(labelText);
|
||||
label.appendChild(inputElement);
|
||||
|
||||
this.inputControls.appendChild(label);
|
||||
} else {
|
||||
console.warn('Unknown custom input type. Only checkbox and text are supported.', input);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// Set the default button class
|
||||
@@ -529,7 +555,8 @@ export class Popup {
|
||||
this.inputResults = new Map(this.customInputs.map(input => {
|
||||
/** @type {HTMLInputElement} */
|
||||
const inputControl = this.dlg.querySelector(`#${input.id}`);
|
||||
return [inputControl.id, inputControl.checked];
|
||||
const value = input.type === 'text' ? inputControl.value : inputControl.checked;
|
||||
return [inputControl.id, value];
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -619,7 +646,7 @@ export class Popup {
|
||||
/** @readonly @type {Popup[]} Remember all popups */
|
||||
popups: [],
|
||||
|
||||
/** @type {{value: any, result: POPUP_RESULT|number?, inputResults: Map<string, boolean>?}?} Last popup result */
|
||||
/** @type {{value: any, result: POPUP_RESULT|number?, inputResults: Map<string, string|boolean>?}?} Last popup result */
|
||||
lastResult: null,
|
||||
|
||||
/** @returns {boolean} Checks if any modal popup dialog is open */
|
||||
|
@@ -30,17 +30,23 @@ async function getManifest(extensionPath) {
|
||||
* @returns {Promise<Object>} - Returns the extension information as an object
|
||||
*/
|
||||
async function checkIfRepoIsUpToDate(extensionPath) {
|
||||
const git = simpleGit();
|
||||
await git.cwd(extensionPath).fetch('origin');
|
||||
const currentBranch = await git.cwd(extensionPath).branch();
|
||||
const currentCommitHash = await git.cwd(extensionPath).revparse(['HEAD']);
|
||||
const log = await git.cwd(extensionPath).log({
|
||||
const git = simpleGit({ baseDir: extensionPath });
|
||||
await git.fetch('origin');
|
||||
const currentBranch = await git.branch();
|
||||
const currentCommitHash = await git.revparse(['HEAD']);
|
||||
const log = await git.log({
|
||||
from: currentCommitHash,
|
||||
to: `origin/${currentBranch.current}`,
|
||||
});
|
||||
|
||||
// Fetch remote repository information
|
||||
const remotes = await git.cwd(extensionPath).getRemotes(true);
|
||||
const remotes = await git.getRemotes(true);
|
||||
if (remotes.length === 0) {
|
||||
return {
|
||||
isUpToDate: true,
|
||||
remoteUrl: '',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
isUpToDate: log.total === 0,
|
||||
@@ -76,7 +82,7 @@ router.post('/install', async (request, response) => {
|
||||
fs.mkdirSync(PUBLIC_DIRECTORIES.globalExtensions);
|
||||
}
|
||||
|
||||
const { url, global } = request.body;
|
||||
const { url, global, branch } = request.body;
|
||||
|
||||
if (global && !request.user.profile.admin) {
|
||||
console.error(`User ${request.user.profile.handle} does not have permission to install global extensions.`);
|
||||
@@ -90,8 +96,12 @@ router.post('/install', async (request, response) => {
|
||||
return response.status(409).send(`Directory already exists at ${extensionPath}`);
|
||||
}
|
||||
|
||||
await git.clone(url, extensionPath, { '--depth': 1 });
|
||||
console.info(`Extension has been cloned at ${extensionPath}`);
|
||||
const cloneOptions = { '--depth': 1 };
|
||||
if (branch) {
|
||||
cloneOptions['--branch'] = branch;
|
||||
}
|
||||
await git.clone(url, extensionPath, cloneOptions);
|
||||
console.info(`Extension has been cloned to ${extensionPath} from ${url} at ${branch || '(default)'} branch`);
|
||||
|
||||
const { version, author, display_name } = await getManifest(extensionPath);
|
||||
|
||||
@@ -114,7 +124,6 @@ router.post('/install', async (request, response) => {
|
||||
* @returns {void}
|
||||
*/
|
||||
router.post('/update', async (request, response) => {
|
||||
const git = simpleGit();
|
||||
if (!request.body.extensionName) {
|
||||
return response.status(400).send('Bad Request: extensionName is required in the request body.');
|
||||
}
|
||||
@@ -128,22 +137,23 @@ router.post('/update', async (request, response) => {
|
||||
}
|
||||
|
||||
const basePath = global ? PUBLIC_DIRECTORIES.globalExtensions : request.user.directories.extensions;
|
||||
const extensionPath = path.join(basePath, extensionName);
|
||||
const extensionPath = path.join(basePath, sanitize(extensionName));
|
||||
|
||||
if (!fs.existsSync(extensionPath)) {
|
||||
return response.status(404).send(`Directory does not exist at ${extensionPath}`);
|
||||
}
|
||||
|
||||
const { isUpToDate, remoteUrl } = await checkIfRepoIsUpToDate(extensionPath);
|
||||
const currentBranch = await git.cwd(extensionPath).branch();
|
||||
const git = simpleGit({ baseDir: extensionPath });
|
||||
const currentBranch = await git.branch();
|
||||
if (!isUpToDate) {
|
||||
await git.cwd(extensionPath).pull('origin', currentBranch.current);
|
||||
await git.pull('origin', currentBranch.current);
|
||||
console.info(`Extension has been updated at ${extensionPath}`);
|
||||
} else {
|
||||
console.info(`Extension is up to date at ${extensionPath}`);
|
||||
}
|
||||
await git.cwd(extensionPath).fetch('origin');
|
||||
const fullCommitHash = await git.cwd(extensionPath).revparse(['HEAD']);
|
||||
await git.fetch('origin');
|
||||
const fullCommitHash = await git.revparse(['HEAD']);
|
||||
const shortCommitHash = fullCommitHash.slice(0, 7);
|
||||
|
||||
return response.send({ shortCommitHash, extensionPath, isUpToDate, remoteUrl });
|
||||
@@ -154,6 +164,110 @@ router.post('/update', async (request, response) => {
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/branches', async (request, response) => {
|
||||
try {
|
||||
const { extensionName, global } = request.body;
|
||||
|
||||
if (!extensionName) {
|
||||
return response.status(400).send('Bad Request: extensionName is required in the request body.');
|
||||
}
|
||||
|
||||
if (global && !request.user.profile.admin) {
|
||||
console.error(`User ${request.user.profile.handle} does not have permission to list branches of global extensions.`);
|
||||
return response.status(403).send('Forbidden: No permission to list branches of global extensions.');
|
||||
}
|
||||
|
||||
const basePath = global ? PUBLIC_DIRECTORIES.globalExtensions : request.user.directories.extensions;
|
||||
const extensionPath = path.join(basePath, sanitize(extensionName));
|
||||
|
||||
if (!fs.existsSync(extensionPath)) {
|
||||
return response.status(404).send(`Directory does not exist at ${extensionPath}`);
|
||||
}
|
||||
|
||||
const git = simpleGit({ baseDir: extensionPath });
|
||||
// Unshallow the repository if it is shallow
|
||||
const isShallow = await git.revparse(['--is-shallow-repository']) === 'true';
|
||||
if (isShallow) {
|
||||
console.info(`Unshallowing the repository at ${extensionPath}`);
|
||||
await git.fetch('origin', ['--unshallow']);
|
||||
}
|
||||
|
||||
// Fetch all branches
|
||||
await git.remote(['set-branches', 'origin', '*']);
|
||||
await git.fetch('origin');
|
||||
const localBranches = await git.branchLocal();
|
||||
const remoteBranches = await git.branch(['-r', '--list', 'origin/*']);
|
||||
const result = [
|
||||
...Object.values(localBranches.branches),
|
||||
...Object.values(remoteBranches.branches),
|
||||
].map(b => ({ current: b.current, commit: b.commit, name: b.name, label: b.label }));
|
||||
|
||||
return response.send(result);
|
||||
} catch (error) {
|
||||
console.error('Getting branches failed', error);
|
||||
return response.status(500).send('Internal Server Error. Check the server logs for more details.');
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/switch', async (request, response) => {
|
||||
try {
|
||||
const { extensionName, branch, global } = request.body;
|
||||
|
||||
if (!extensionName || !branch) {
|
||||
return response.status(400).send('Bad Request: extensionName and branch are required in the request body.');
|
||||
}
|
||||
|
||||
if (global && !request.user.profile.admin) {
|
||||
console.error(`User ${request.user.profile.handle} does not have permission to switch branches of global extensions.`);
|
||||
return response.status(403).send('Forbidden: No permission to switch branches of global extensions.');
|
||||
}
|
||||
|
||||
const basePath = global ? PUBLIC_DIRECTORIES.globalExtensions : request.user.directories.extensions;
|
||||
const extensionPath = path.join(basePath, sanitize(extensionName));
|
||||
|
||||
if (!fs.existsSync(extensionPath)) {
|
||||
return response.status(404).send(`Directory does not exist at ${extensionPath}`);
|
||||
}
|
||||
|
||||
const git = simpleGit({ baseDir: extensionPath });
|
||||
const branches = await git.branchLocal();
|
||||
|
||||
if (String(branch).startsWith('origin/')) {
|
||||
const localBranch = branch.replace('origin/', '');
|
||||
if (branches.all.includes(localBranch)) {
|
||||
console.info(`Branch ${localBranch} already exists locally, checking it out`);
|
||||
await git.checkout(localBranch);
|
||||
return response.sendStatus(204);
|
||||
}
|
||||
|
||||
console.info(`Branch ${localBranch} does not exist locally, creating it from ${branch}`);
|
||||
await git.checkoutBranch(localBranch, branch);
|
||||
return response.sendStatus(204);
|
||||
}
|
||||
|
||||
if (!branches.all.includes(branch)) {
|
||||
console.error(`Branch ${branch} does not exist locally`);
|
||||
return response.status(404).send(`Branch ${branch} does not exist locally`);
|
||||
}
|
||||
|
||||
// Check if the branch is already checked out
|
||||
const currentBranch = await git.branch();
|
||||
if (currentBranch.current === branch) {
|
||||
console.info(`Branch ${branch} is already checked out`);
|
||||
return response.sendStatus(204);
|
||||
}
|
||||
|
||||
// Checkout the branch
|
||||
await git.checkout(branch);
|
||||
console.info(`Checked out branch ${branch} at ${extensionPath}`);
|
||||
|
||||
return response.sendStatus(204);
|
||||
} catch (error) {
|
||||
console.error('Switching branches failed', error);
|
||||
return response.status(500).send('Internal Server Error. Check the server logs for more details.');
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/move', async (request, response) => {
|
||||
try {
|
||||
const { extensionName, source, destination } = request.body;
|
||||
@@ -194,7 +308,7 @@ router.post('/move', async (request, response) => {
|
||||
return response.sendStatus(204);
|
||||
} catch (error) {
|
||||
console.error('Moving extension failed', error);
|
||||
return response.status(500).send('Internal Server Error. Try again later.');
|
||||
return response.status(500).send('Internal Server Error. Check the server logs for more details.');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -209,7 +323,6 @@ router.post('/move', async (request, response) => {
|
||||
* @returns {void}
|
||||
*/
|
||||
router.post('/version', async (request, response) => {
|
||||
const git = simpleGit();
|
||||
if (!request.body.extensionName) {
|
||||
return response.status(400).send('Bad Request: extensionName is required in the request body.');
|
||||
}
|
||||
@@ -223,19 +336,20 @@ router.post('/version', async (request, response) => {
|
||||
return response.status(404).send(`Directory does not exist at ${extensionPath}`);
|
||||
}
|
||||
|
||||
const git = simpleGit({ baseDir: extensionPath });
|
||||
let currentCommitHash;
|
||||
try {
|
||||
currentCommitHash = await git.cwd(extensionPath).revparse(['HEAD']);
|
||||
currentCommitHash = await git.revparse(['HEAD']);
|
||||
} catch (error) {
|
||||
// it is not a git repo, or has no commits yet, or is a bare repo
|
||||
// not possible to update it, most likely can't get the branch name either
|
||||
return response.send({ currentBranchName: '', currentCommitHash: '', isUpToDate: true, remoteUrl: '' });
|
||||
}
|
||||
|
||||
const currentBranch = await git.cwd(extensionPath).branch();
|
||||
const currentBranch = await git.branch();
|
||||
// get only the working branch
|
||||
const currentBranchName = currentBranch.current;
|
||||
await git.cwd(extensionPath).fetch('origin');
|
||||
await git.fetch('origin');
|
||||
console.debug(extensionName, currentBranchName, currentCommitHash);
|
||||
const { isUpToDate, remoteUrl } = await checkIfRepoIsUpToDate(extensionPath);
|
||||
|
||||
|
Reference in New Issue
Block a user