mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-20 00:05:22 +00:00
124 lines
No EOL
3.6 KiB
TypeScript
124 lines
No EOL
3.6 KiB
TypeScript
import { GitRepository, AppContext } from './types.js';
|
|
import { simpleGit, SimpleGitProgressEvent } from 'simple-git';
|
|
import { createLogger } from './logger.js';
|
|
import { GitConfig } from "@sourcebot/schemas/v2/index.type"
|
|
import path from 'path';
|
|
|
|
const logger = createLogger('git');
|
|
|
|
export const cloneRepository = async (cloneURL: string, path: string, gitConfig?: Record<string, string>, onProgress?: (event: SimpleGitProgressEvent) => void) => {
|
|
const git = simpleGit({
|
|
progress: onProgress,
|
|
});
|
|
|
|
const configParams = Object.entries(gitConfig ?? {}).flatMap(
|
|
([key, value]) => ['--config', `${key}=${value}`]
|
|
);
|
|
|
|
await git.clone(
|
|
cloneURL,
|
|
path,
|
|
[
|
|
"--bare",
|
|
...configParams
|
|
]
|
|
);
|
|
|
|
await git.cwd({
|
|
path,
|
|
}).addConfig("remote.origin.fetch", "+refs/heads/*:refs/heads/*");
|
|
}
|
|
|
|
|
|
export const fetchRepository = async (path: string, onProgress?: (event: SimpleGitProgressEvent) => void) => {
|
|
const git = simpleGit({
|
|
progress: onProgress,
|
|
});
|
|
|
|
await git.cwd({
|
|
path: path,
|
|
}).fetch(
|
|
"origin",
|
|
[
|
|
"--prune",
|
|
"--progress"
|
|
]
|
|
);
|
|
}
|
|
|
|
const isValidGitRepo = async (url: string): Promise<boolean> => {
|
|
const git = simpleGit();
|
|
try {
|
|
await git.listRemote([url]);
|
|
return true;
|
|
} catch (error) {
|
|
logger.debug(`Error checking if ${url} is a valid git repo: ${error}`);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
const stripProtocolAndGitSuffix = (url: string): string => {
|
|
return url.replace(/^[a-zA-Z]+:\/\//, '').replace(/\.git$/, '');
|
|
}
|
|
|
|
const getRepoNameFromUrl = (url: string): string => {
|
|
const strippedUrl = stripProtocolAndGitSuffix(url);
|
|
return strippedUrl.split('/').slice(-2).join('/');
|
|
}
|
|
|
|
export const getGitRepoFromConfig = async (config: GitConfig, ctx: AppContext) => {
|
|
const repoValid = await isValidGitRepo(config.url);
|
|
if (!repoValid) {
|
|
logger.error(`Git repo provided in config with url ${config.url} is not valid`);
|
|
return null;
|
|
}
|
|
|
|
const cloneUrl = config.url;
|
|
const repoId = stripProtocolAndGitSuffix(cloneUrl);
|
|
const repoName = getRepoNameFromUrl(config.url);
|
|
const repoPath = path.resolve(path.join(ctx.reposPath, `${repoId}.git`));
|
|
const repo: GitRepository = {
|
|
vcs: 'git',
|
|
id: repoId,
|
|
name: repoName,
|
|
path: repoPath,
|
|
isStale: false,
|
|
cloneUrl: cloneUrl,
|
|
branches: [],
|
|
tags: [],
|
|
}
|
|
|
|
if (config.revisions) {
|
|
if (config.revisions.branches) {
|
|
const branchGlobs = config.revisions.branches;
|
|
const git = simpleGit();
|
|
const branchList = await git.listRemote(['--heads', cloneUrl]);
|
|
const branches = branchList
|
|
.split('\n')
|
|
.map(line => line.split('\t')[1])
|
|
.filter(Boolean)
|
|
.map(branch => branch.replace('refs/heads/', ''));
|
|
|
|
repo.branches = branches.filter(branch =>
|
|
branchGlobs.some(glob => new RegExp(glob).test(branch))
|
|
);
|
|
}
|
|
|
|
if (config.revisions.tags) {
|
|
const tagGlobs = config.revisions.tags;
|
|
const git = simpleGit();
|
|
const tagList = await git.listRemote(['--tags', cloneUrl]);
|
|
const tags = tagList
|
|
.split('\n')
|
|
.map(line => line.split('\t')[1])
|
|
.filter(Boolean)
|
|
.map(tag => tag.replace('refs/tags/', ''));
|
|
|
|
repo.tags = tags.filter(tag =>
|
|
tagGlobs.some(glob => new RegExp(glob).test(tag))
|
|
);
|
|
}
|
|
}
|
|
|
|
return repo;
|
|
} |