feat: первая версия

This commit is contained in:
2025-05-15 20:50:36 +04:00
parent 769753a6b0
commit ccf328773f
17 changed files with 877 additions and 2 deletions

130
git/git-loader.ts Normal file
View File

@@ -0,0 +1,130 @@
import path from 'path';
import fsSync from 'fs';
import fs from 'fs/promises';
const { promises, ...isoGitFs } = fsSync;
import * as http from 'isomorphic-git/http/node';
import * as git from 'isomorphic-git';
import type { AppConfiguration } from '../config/app-configuration';
import { logger } from '../config/logger';
export class GitLoader {
constructor(private readonly config: AppConfiguration) {
logger.info('GitLoader instantiated');
}
private async init() {
try {
const dir = path.resolve(this.config.pathToSave);
if (!fsSync.existsSync(dir)) {
await fs.mkdir(dir, { recursive: true });
logger.info(`Directory ${dir} created`);
}
} catch (e: unknown) {
logger.error('Failed to create directory:', e);
throw new Error(`Failed to create directory: ${e}`);
}
}
public async loadRepo() {
await this.init();
const dir = path.resolve(this.config.pathToSave);
logger.info(
`Start cloning repository from ${this.config.gitPath} to ${dir}`,
);
try {
let cloneCompleted = false;
let lastProgressUpdate = Date.now();
let lastProgressMessage = '';
const progressTimer = setInterval(() => {
const now = Date.now();
if (now - lastProgressUpdate > 180000 && !cloneCompleted) {
logger.warn(
'No progress updates for 3 minutes, operation might be stuck',
);
}
}, 60000);
await git.clone({
fs: isoGitFs,
http,
dir,
url: this.config.gitPath,
singleBranch: true,
depth: 1,
onAuth: () => {
logger.info('Authentication required');
return {
username: this.config.sensitiveData.userEmail,
password: this.config.sensitiveData.password,
};
},
onAuthFailure: (error: unknown) => {
logger.error(
'Authentication failed:',
error,
'try to made repo public, auth don`t work now',
);
throw new Error('Authentication failed');
},
onAuthSuccess: () => {
logger.info('Authentication successful');
},
onProgress: (progress: any) => {
const progressMessage = JSON.stringify(progress);
if (progressMessage !== lastProgressMessage) {
lastProgressMessage = progressMessage;
logger.info('Progress:', progress);
}
},
corsProxy: 'https://cors.isomorphic-git.org',
});
cloneCompleted = true;
clearInterval(progressTimer);
logger.info('Clone successful');
} catch (e: unknown) {
logger.error('Error cloning repository:', e);
throw new Error(`GitLoader: ${e}`);
}
}
public async checkoutBranch(branch: string) {
try {
const dir = path.resolve(this.config.pathToSave);
logger.info(`Checking out branch ${branch} in ${dir}`);
const branches = await git.listBranches({
fs: isoGitFs,
dir,
gitdir: this.config.gitPath,
});
logger.info(`Available branches: ${branches.join(', ')}`);
await git.checkout({
fs: isoGitFs,
dir,
ref: branch,
});
logger.info(`Checked out branch ${branch} successfully`);
} catch (e: unknown) {
logger.error('Error checking out branch:', e);
try {
const dir = path.resolve(this.config.pathToSave);
logger.info(`Trying to use HEAD instead of branch`);
await git.checkout({
fs: isoGitFs,
dir,
ref: 'HEAD',
});
logger.info(`Used HEAD successfully`);
} catch (headError) {
logger.error('Error checking out HEAD:', headError);
throw new Error(`GitLoader CheckoutBranch error: ${e}`);
}
}
}
}

36
git/index.ts Normal file
View File

@@ -0,0 +1,36 @@
import { GitLoader } from './git-loader';
import { logger } from '../config/logger';
import type { AppConfiguration } from '../config/app-configuration';
export class GitService {
private readonly gitLoader: GitLoader;
constructor(config: AppConfiguration) {
logger.info('GitService initialized');
this.gitLoader = new GitLoader(config);
}
public async getRepo(branch: string = 'main'): Promise<void> {
try {
logger.info(`Cloning repo with target branch: ${branch}...`);
const cloneStartTime = Date.now();
await this.gitLoader.loadRepo();
const cloneEndTime = Date.now();
const cloneTimeSeconds = ((cloneEndTime - cloneStartTime) / 1000).toFixed(
2,
);
logger.info(`Repo cloned successfully in ${cloneTimeSeconds} seconds`);
logger.info(`Checking out branch ${branch}...`);
await this.gitLoader.checkoutBranch(branch);
logger.info('Branch checked out successfully');
} catch (e: unknown) {
logger.error('Error cloning repo:', e instanceof Error ? e.message : e);
throw new Error(`GitService: ${e}`);
}
}
}