Update Gitea-Sektion:
Branch-Auswahl
Dieser Commit ist enthalten in:
@ -414,24 +414,58 @@ router.post('/set-remote/:projectId', (req, res) => {
|
||||
/**
|
||||
* POST /api/git/init-push/:projectId
|
||||
* Initialen Push mit Upstream-Tracking
|
||||
* Body: { targetBranch?: string, force?: boolean }
|
||||
* - targetBranch: Optional - Ziel-Branch auf Remote (z.B. "main" auch wenn lokal "master")
|
||||
* - force: Optional - Force-Push um Remote zu überschreiben
|
||||
*/
|
||||
router.post('/init-push/:projectId', (req, res) => {
|
||||
router.post('/init-push/:projectId', async (req, res) => {
|
||||
try {
|
||||
const { projectId } = req.params;
|
||||
const { branch } = req.body;
|
||||
const { targetBranch, force } = req.body;
|
||||
const application = getApplicationForProject(projectId);
|
||||
|
||||
if (!application) {
|
||||
return res.status(404).json({ error: 'Keine Anwendung für dieses Projekt konfiguriert' });
|
||||
}
|
||||
|
||||
const currentBranch = branch || 'main';
|
||||
const result = gitService.pushWithUpstream(application.local_path, currentBranch);
|
||||
// targetBranch kann null sein - dann wird der lokale Branch-Name verwendet
|
||||
// force: boolean - überschreibt Remote-Branch bei Konflikten
|
||||
const result = gitService.pushWithUpstream(application.local_path, targetBranch || null, 'origin', force === true);
|
||||
|
||||
if (result.success) {
|
||||
// Sync-Zeitpunkt aktualisieren
|
||||
const db = getDb();
|
||||
db.prepare('UPDATE applications SET last_sync = CURRENT_TIMESTAMP WHERE project_id = ?').run(projectId);
|
||||
|
||||
// Default-Branch in Gitea aktualisieren wenn der gepushte Branch abweicht
|
||||
if (application.gitea_repo_url && result.branch) {
|
||||
try {
|
||||
// Owner/Repo aus URL extrahieren (z.B. https://gitea.../AegisSight/TaskMate.git)
|
||||
const urlMatch = application.gitea_repo_url.match(/\/([^\/]+)\/([^\/]+?)(?:\.git)?$/);
|
||||
if (urlMatch) {
|
||||
const owner = urlMatch[1];
|
||||
const repoName = urlMatch[2];
|
||||
const actualBranch = result.branch;
|
||||
|
||||
// Default-Branch in Gitea setzen
|
||||
const updateResult = await giteaService.updateRepository(owner, repoName, {
|
||||
defaultBranch: actualBranch
|
||||
});
|
||||
|
||||
if (updateResult.success) {
|
||||
logger.info(`Default-Branch in Gitea auf '${actualBranch}' gesetzt für ${owner}/${repoName}`);
|
||||
result.giteaUpdated = true;
|
||||
result.defaultBranch = actualBranch;
|
||||
} else {
|
||||
logger.warn(`Konnte Default-Branch in Gitea nicht aktualisieren: ${updateResult.error}`);
|
||||
result.giteaUpdated = false;
|
||||
}
|
||||
}
|
||||
} catch (giteaError) {
|
||||
logger.warn('Fehler beim Aktualisieren des Default-Branch in Gitea:', giteaError);
|
||||
result.giteaUpdated = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res.json(result);
|
||||
@ -441,4 +475,31 @@ router.post('/init-push/:projectId', (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* POST /api/git/rename-branch/:projectId
|
||||
* Branch umbenennen
|
||||
* Body: { oldName: string, newName: string }
|
||||
*/
|
||||
router.post('/rename-branch/:projectId', (req, res) => {
|
||||
try {
|
||||
const { projectId } = req.params;
|
||||
const { oldName, newName } = req.body;
|
||||
const application = getApplicationForProject(projectId);
|
||||
|
||||
if (!application) {
|
||||
return res.status(404).json({ error: 'Keine Anwendung für dieses Projekt konfiguriert' });
|
||||
}
|
||||
|
||||
if (!oldName || !newName) {
|
||||
return res.status(400).json({ error: 'oldName und newName sind erforderlich' });
|
||||
}
|
||||
|
||||
const result = gitService.renameBranch(application.local_path, oldName, newName);
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
logger.error('Fehler beim Umbenennen des Branches:', error);
|
||||
res.status(500).json({ error: 'Serverfehler' });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
@ -443,7 +443,7 @@ function hasRemote(localPath, remoteName = 'origin') {
|
||||
/**
|
||||
* Initialen Push mit Upstream-Tracking
|
||||
*/
|
||||
function pushWithUpstream(localPath, branch = null, remoteName = 'origin') {
|
||||
function pushWithUpstream(localPath, targetBranch = null, remoteName = 'origin', force = false) {
|
||||
if (!isGitRepository(localPath)) {
|
||||
return { success: false, error: 'Kein Git-Repository' };
|
||||
}
|
||||
@ -477,11 +477,12 @@ function pushWithUpstream(localPath, branch = null, remoteName = 'origin') {
|
||||
}
|
||||
}
|
||||
|
||||
// Aktuellen Branch ermitteln NACH dem Commit
|
||||
// Aktuellen (lokalen) Branch ermitteln NACH dem Commit
|
||||
let localBranch = null;
|
||||
const branchResult = execGitCommand('git branch --show-current', localPath);
|
||||
if (branchResult.success && branchResult.output) {
|
||||
branch = branchResult.output;
|
||||
logger.info(`Aktueller Branch: ${branch}`);
|
||||
localBranch = branchResult.output;
|
||||
logger.info(`Lokaler Branch: ${localBranch}`);
|
||||
} else {
|
||||
// Fallback: Branch aus git branch auslesen
|
||||
const branchListResult = execGitCommand('git branch', localPath);
|
||||
@ -491,29 +492,46 @@ function pushWithUpstream(localPath, branch = null, remoteName = 'origin') {
|
||||
const lines = branchListResult.output.split('\n');
|
||||
for (const line of lines) {
|
||||
if (line.includes('*')) {
|
||||
branch = line.replace('*', '').trim();
|
||||
localBranch = line.replace('*', '').trim();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!branch) {
|
||||
if (!localBranch) {
|
||||
// Letzter Fallback: Versuche den Branch zu erstellen
|
||||
logger.info('Kein Branch gefunden, erstelle main');
|
||||
execGitCommand('git checkout -b main', localPath);
|
||||
branch = 'main';
|
||||
localBranch = 'main';
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(`Push auf Branch: ${branch}`);
|
||||
// Wenn kein Ziel-Branch angegeben, verwende lokalen Branch-Namen
|
||||
const remoteBranch = targetBranch || localBranch;
|
||||
|
||||
logger.info(`Push: lokaler Branch '${localBranch}' → Remote Branch '${remoteBranch}'${force ? ' (FORCE)' : ''}`);
|
||||
|
||||
// Push mit -u für Upstream-Tracking
|
||||
const pushResult = execGitCommand(`git push -u ${remoteName} ${branch}`, localPath, { timeout: 120000 });
|
||||
// Format: git push -u origin localBranch:remoteBranch
|
||||
const forceFlag = force ? ' --force' : '';
|
||||
let pushCommand;
|
||||
if (localBranch === remoteBranch) {
|
||||
pushCommand = `git push -u${forceFlag} ${remoteName} ${localBranch}`;
|
||||
} else {
|
||||
// Branch-Mapping: lokalen Branch auf anderen Remote-Branch pushen
|
||||
pushCommand = `git push -u${forceFlag} ${remoteName} ${localBranch}:${remoteBranch}`;
|
||||
}
|
||||
|
||||
const pushResult = execGitCommand(pushCommand, localPath, { timeout: 120000 });
|
||||
|
||||
if (!pushResult.success) {
|
||||
logger.error(`Push fehlgeschlagen: ${pushResult.error}`);
|
||||
}
|
||||
|
||||
// Branch-Namen im Ergebnis inkludieren für Default-Branch Aktualisierung
|
||||
pushResult.localBranch = localBranch;
|
||||
pushResult.branch = remoteBranch; // Remote-Branch für Gitea Default-Branch
|
||||
|
||||
return pushResult;
|
||||
}
|
||||
|
||||
@ -561,6 +579,39 @@ function prepareForGitea(localPath, remoteUrl, options = {}) {
|
||||
return { success: true, message: 'Repository für Gitea vorbereitet' };
|
||||
}
|
||||
|
||||
/**
|
||||
* Branch umbenennen
|
||||
*/
|
||||
function renameBranch(localPath, oldName, newName) {
|
||||
if (!isGitRepository(localPath)) {
|
||||
return { success: false, error: 'Kein Git-Repository' };
|
||||
}
|
||||
|
||||
// Validiere neuen Branch-Namen
|
||||
if (!newName || !/^[a-zA-Z0-9_\-]+$/.test(newName)) {
|
||||
return { success: false, error: 'Ungültiger Branch-Name. Nur Buchstaben, Zahlen, Unterstriche und Bindestriche erlaubt.' };
|
||||
}
|
||||
|
||||
// Prüfe ob wir auf dem zu umbenennenden Branch sind
|
||||
const branchResult = execGitCommand('git branch --show-current', localPath);
|
||||
const currentBranch = branchResult.success ? branchResult.output : null;
|
||||
|
||||
if (currentBranch !== oldName) {
|
||||
return { success: false, error: `Bitte wechsle zuerst zum Branch "${oldName}" bevor du ihn umbenennst.` };
|
||||
}
|
||||
|
||||
// Branch umbenennen
|
||||
const renameResult = execGitCommand(`git branch -m ${oldName} ${newName}`, localPath);
|
||||
|
||||
if (!renameResult.success) {
|
||||
logger.error(`Branch umbenennen fehlgeschlagen: ${renameResult.error}`);
|
||||
return renameResult;
|
||||
}
|
||||
|
||||
logger.info(`Branch umbenannt: ${oldName} → ${newName}`);
|
||||
return { success: true, oldName, newName, message: `Branch "${oldName}" zu "${newName}" umbenannt` };
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
windowsToContainerPath,
|
||||
containerToWindowsPath,
|
||||
@ -581,5 +632,6 @@ module.exports = {
|
||||
setRemote,
|
||||
hasRemote,
|
||||
pushWithUpstream,
|
||||
prepareForGitea
|
||||
prepareForGitea,
|
||||
renameBranch
|
||||
};
|
||||
|
||||
@ -284,12 +284,44 @@ function getSafeCloneUrl(cloneUrl) {
|
||||
return cloneUrl.replace(/https:\/\/[^@]+@/, 'https://');
|
||||
}
|
||||
|
||||
/**
|
||||
* Repository-Einstellungen aktualisieren (z.B. default_branch ändern)
|
||||
*/
|
||||
async function updateRepository(owner, repo, options = {}) {
|
||||
try {
|
||||
const updateData = {};
|
||||
if (options.defaultBranch) updateData.default_branch = options.defaultBranch;
|
||||
if (options.description !== undefined) updateData.description = options.description;
|
||||
if (options.private !== undefined) updateData.private = options.private;
|
||||
|
||||
const repoData = await giteaFetch(`/repos/${owner}/${repo}`, {
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(updateData)
|
||||
});
|
||||
|
||||
logger.info(`Repository ${owner}/${repo} aktualisiert (default_branch: ${repoData.default_branch})`);
|
||||
return {
|
||||
success: true,
|
||||
repository: {
|
||||
id: repoData.id,
|
||||
name: repoData.name,
|
||||
fullName: repoData.full_name,
|
||||
defaultBranch: repoData.default_branch
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error(`Fehler beim Aktualisieren des Repositories ${owner}/${repo}:`, error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
listRepositories,
|
||||
getRepository,
|
||||
getRepositoryBranches,
|
||||
getRepositoryCommits,
|
||||
createRepository,
|
||||
updateRepository,
|
||||
deleteRepository,
|
||||
getCurrentUser,
|
||||
testConnection,
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren