Files
ProxmoxVE-Local/src/server/lib/git.ts
Rögl-Brunner Michel 6ee5c5c017 PoC
2025-09-09 14:24:36 +02:00

178 lines
5.0 KiB
TypeScript

import { simpleGit, SimpleGit } from 'simple-git';
import { env } from '~/env.js';
import { join } from 'path';
export class GitManager {
private git: SimpleGit;
private repoPath: string;
private scriptsDir: string;
constructor() {
this.repoPath = process.cwd();
this.scriptsDir = join(this.repoPath, env.SCRIPTS_DIRECTORY);
this.git = simpleGit(this.repoPath);
}
/**
* Check if the repository is behind the remote
*/
async isBehindRemote(): Promise<boolean> {
try {
if (!env.REPO_URL) {
return false; // No remote configured
}
// Fetch latest changes without merging
await this.git.fetch();
// Check if local branch is behind remote
const status = await this.git.status();
const behind = status.behind > 0;
return behind;
} catch (error) {
console.error('Error checking repo status:', error);
return false;
}
}
/**
* Pull updates from remote repository
*/
async pullUpdates(): Promise<{ success: boolean; message: string }> {
try {
if (!env.REPO_URL) {
return { success: false, message: 'No remote repository configured' };
}
// Check if we're in a git repository
const isRepo = await this.git.checkIsRepo();
if (!isRepo) {
// Clone the repository if it doesn't exist
return await this.cloneRepository();
}
// Pull latest changes
const result = await this.git.pull(env.REPO_BRANCH);
return {
success: true,
message: `Successfully pulled updates. ${result.summary.changes} changes, ${result.summary.insertions} insertions, ${result.summary.deletions} deletions`
};
} catch (error) {
console.error('Error pulling updates:', error);
return {
success: false,
message: `Failed to pull updates: ${error instanceof Error ? error.message : 'Unknown error'}`
};
}
}
/**
* Clone the repository if it doesn't exist
*/
private async cloneRepository(): Promise<{ success: boolean; message: string }> {
try {
if (!env.REPO_URL) {
return { success: false, message: 'No repository URL configured' };
}
console.log(`Cloning repository from ${env.REPO_URL}...`);
// Clone the repository
await this.git.clone(env.REPO_URL, this.repoPath, {
'--branch': env.REPO_BRANCH,
'--single-branch': true,
'--depth': 1
});
return {
success: true,
message: `Successfully cloned repository from ${env.REPO_URL}`
};
} catch (error) {
console.error('Error cloning repository:', error);
return {
success: false,
message: `Failed to clone repository: ${error instanceof Error ? error.message : 'Unknown error'}`
};
}
}
/**
* Initialize repository on startup if needed
*/
async initializeRepository(): Promise<void> {
try {
if (!env.REPO_URL) {
console.log('No remote repository configured, skipping initialization');
return;
}
const isRepo = await this.git.checkIsRepo();
if (!isRepo) {
console.log('Repository not found, cloning...');
const result = await this.cloneRepository();
if (result.success) {
console.log('Repository initialized successfully');
} else {
console.error('Failed to initialize repository:', result.message);
}
} else {
console.log('Repository already exists, checking for updates...');
const behind = await this.isBehindRemote();
if (behind) {
console.log('Repository is behind remote, pulling updates...');
const result = await this.pullUpdates();
if (result.success) {
console.log('Repository updated successfully');
} else {
console.error('Failed to update repository:', result.message);
}
} else {
console.log('Repository is up to date');
}
}
} catch (error) {
console.error('Error initializing repository:', error);
}
}
/**
* Get repository status information
*/
async getStatus(): Promise<{
isRepo: boolean;
isBehind: boolean;
lastCommit?: string;
branch?: string;
}> {
try {
const isRepo = await this.git.checkIsRepo();
if (!isRepo) {
return { isRepo: false, isBehind: false };
}
const isBehind = await this.isBehindRemote();
const log = await this.git.log({ maxCount: 1 });
const status = await this.git.status();
return {
isRepo: true,
isBehind,
lastCommit: log.latest?.hash,
branch: status.current
};
} catch (error) {
console.error('Error getting repository status:', error);
return { isRepo: false, isBehind: false };
}
}
}
// Export singleton instance
export const gitManager = new GitManager();
// Initialize repository on module load
gitManager.initializeRepository().catch(console.error);