be8aef44fe
Build and Deploy Verso / deploy (push) Successful in 12m48s
Two new boolean fields on the project (gitSyncPushFiles, gitSyncPushPdf, both default true) let users control what gets pushed independently: - "Push project files" switch — skip all docs/binary files when off - "Push compiled PDF" switch — grayed out when no pdfPath is set The push button and auto-push are disabled when both switches would result in nothing being pushed. Config is stored in MongoDB so settings persist per-project. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
101 lines
3.3 KiB
JavaScript
101 lines
3.3 KiB
JavaScript
import logger from '@overleaf/logger'
|
|
import GitSyncHandler from './GitSyncHandler.mjs'
|
|
import SessionManager from '../Authentication/SessionManager.mjs'
|
|
import { expressify } from '@overleaf/promise-utils'
|
|
|
|
async function configureGitSync(req, res) {
|
|
const projectId = req.params.project_id
|
|
const { remoteUrl, subPath = '', pdfPath = '', pushFiles = true, pushPdf = true } = req.body
|
|
|
|
if (typeof remoteUrl !== 'string' || remoteUrl.trim() === '') {
|
|
return res.status(400).json({ error: 'remoteUrl is required' })
|
|
}
|
|
|
|
const trimmedUrl = remoteUrl.trim()
|
|
if (!trimmedUrl.startsWith('https://') && !trimmedUrl.startsWith('git@')) {
|
|
return res.status(400).json({ error: 'remoteUrl must start with https:// or git@' })
|
|
}
|
|
|
|
const trimmedSubPath = String(subPath).trim().replace(/^\/+|\/+$/g, '')
|
|
if (trimmedSubPath.includes('..')) {
|
|
return res.status(400).json({ error: 'subPath must not contain ..' })
|
|
}
|
|
|
|
const trimmedPdfPath = String(pdfPath).trim().replace(/^\/+/, '')
|
|
if (trimmedPdfPath.includes('..')) {
|
|
return res.status(400).json({ error: 'pdfPath must not contain ..' })
|
|
}
|
|
|
|
await GitSyncHandler.setConfig(projectId, {
|
|
remoteUrl: trimmedUrl,
|
|
subPath: trimmedSubPath,
|
|
pdfPath: trimmedPdfPath,
|
|
pushFiles: Boolean(pushFiles),
|
|
pushPdf: Boolean(pushPdf),
|
|
})
|
|
logger.debug({ projectId }, 'git sync: config saved')
|
|
res.sendStatus(204)
|
|
}
|
|
|
|
async function pushToGit(req, res) {
|
|
const projectId = req.params.project_id
|
|
try {
|
|
const userId = SessionManager.getLoggedInUserId(req.session)
|
|
const { buildId, clsiServerId } = req.body ?? {}
|
|
const { remoteUrl, subPath, pdfPath, pushFiles, pushPdf } =
|
|
await GitSyncHandler.getConfig(projectId)
|
|
if (!remoteUrl) {
|
|
return res.status(400).json({ error: 'No git remote configured for this project' })
|
|
}
|
|
logger.debug({ projectId }, 'git sync: starting push')
|
|
await GitSyncHandler.pushToRemote(projectId, remoteUrl, subPath, {
|
|
pdfPath,
|
|
pdfBuildId: buildId,
|
|
pdfClsiServerId: clsiServerId,
|
|
userId,
|
|
pushFiles,
|
|
pushPdf,
|
|
})
|
|
res.sendStatus(204)
|
|
} catch (err) {
|
|
logger.warn({ err, projectId }, 'git sync: push failed')
|
|
res.status(500).json({ error: err.message })
|
|
}
|
|
}
|
|
|
|
async function pullFromGit(req, res) {
|
|
const projectId = req.params.project_id
|
|
try {
|
|
const userId = SessionManager.getLoggedInUserId(req.session)
|
|
const { remoteUrl, subPath } = await GitSyncHandler.getConfig(projectId)
|
|
if (!remoteUrl) {
|
|
return res.status(400).json({ error: 'No git remote configured for this project' })
|
|
}
|
|
logger.debug({ projectId }, 'git sync: starting pull')
|
|
await GitSyncHandler.pullFromRemote(projectId, remoteUrl, subPath, userId)
|
|
res.sendStatus(204)
|
|
} catch (err) {
|
|
logger.warn({ err, projectId }, 'git sync: pull failed')
|
|
res.status(500).json({ error: err.message })
|
|
}
|
|
}
|
|
|
|
async function getGitSyncConfig(req, res) {
|
|
const projectId = req.params.project_id
|
|
const config = await GitSyncHandler.getConfig(projectId)
|
|
res.json({
|
|
remoteUrl: config.remoteUrl ?? '',
|
|
subPath: config.subPath,
|
|
pdfPath: config.pdfPath,
|
|
pushFiles: config.pushFiles,
|
|
pushPdf: config.pushPdf,
|
|
})
|
|
}
|
|
|
|
export default {
|
|
configureGitSync: expressify(configureGitSync),
|
|
pushToGit: expressify(pushToGit),
|
|
pullFromGit: expressify(pullFromGit),
|
|
getGitSyncConfig: expressify(getGitSyncConfig),
|
|
}
|