mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-13 07:26:26 +00:00
refactor(git): lazy sync git (#6984)
Co-authored-by: Jamie Magee <JamieMagee@users.noreply.github.com>
This commit is contained in:
parent
b45502cd28
commit
062045168a
8 changed files with 53 additions and 29 deletions
|
@ -150,7 +150,7 @@ export async function initRepo({
|
||||||
const url =
|
const url =
|
||||||
defaults.endpoint +
|
defaults.endpoint +
|
||||||
`${encodeURIComponent(projectName)}/_git/${encodeURIComponent(repoName)}`;
|
`${encodeURIComponent(projectName)}/_git/${encodeURIComponent(repoName)}`;
|
||||||
await git.initRepo({
|
git.initRepo({
|
||||||
...config,
|
...config,
|
||||||
localDir,
|
localDir,
|
||||||
url,
|
url,
|
||||||
|
|
|
@ -179,7 +179,7 @@ export async function initRepo({
|
||||||
repository,
|
repository,
|
||||||
});
|
});
|
||||||
|
|
||||||
await git.initRepo({
|
git.initRepo({
|
||||||
...config,
|
...config,
|
||||||
localDir,
|
localDir,
|
||||||
url: gitUrl,
|
url: gitUrl,
|
||||||
|
|
|
@ -153,7 +153,7 @@ export async function initRepo({
|
||||||
repository,
|
repository,
|
||||||
});
|
});
|
||||||
|
|
||||||
await git.initRepo({
|
git.initRepo({
|
||||||
...config,
|
...config,
|
||||||
localDir,
|
localDir,
|
||||||
url,
|
url,
|
||||||
|
|
|
@ -306,7 +306,7 @@ const platform: Platform = {
|
||||||
gitEndpoint.auth = opts.token;
|
gitEndpoint.auth = opts.token;
|
||||||
|
|
||||||
// Initialize Git storage
|
// Initialize Git storage
|
||||||
await git.initRepo({
|
git.initRepo({
|
||||||
...config,
|
...config,
|
||||||
url: URL.format(gitEndpoint),
|
url: URL.format(gitEndpoint),
|
||||||
gitAuthorName: global.gitAuthor?.name,
|
gitAuthorName: global.gitAuthor?.name,
|
||||||
|
|
|
@ -413,7 +413,7 @@ export async function initRepo({
|
||||||
);
|
);
|
||||||
parsedEndpoint.pathname = config.repository + '.git';
|
parsedEndpoint.pathname = config.repository + '.git';
|
||||||
const url = URL.format(parsedEndpoint);
|
const url = URL.format(parsedEndpoint);
|
||||||
await git.initRepo({
|
git.initRepo({
|
||||||
...config,
|
...config,
|
||||||
url,
|
url,
|
||||||
gitAuthorName: global.gitAuthor?.name,
|
gitAuthorName: global.gitAuthor?.name,
|
||||||
|
|
|
@ -224,7 +224,7 @@ export async function initRepo({
|
||||||
repoUrl.auth = 'oauth2:' + opts.token;
|
repoUrl.auth = 'oauth2:' + opts.token;
|
||||||
url = URL.format(repoUrl);
|
url = URL.format(repoUrl);
|
||||||
}
|
}
|
||||||
await git.initRepo({
|
git.initRepo({
|
||||||
...config,
|
...config,
|
||||||
url,
|
url,
|
||||||
gitAuthorName: global.gitAuthor?.name,
|
gitAuthorName: global.gitAuthor?.name,
|
||||||
|
|
|
@ -60,7 +60,7 @@ describe('platform/git', () => {
|
||||||
const repo = Git(origin.path);
|
const repo = Git(origin.path);
|
||||||
await repo.clone(base.path, '.', ['--bare']);
|
await repo.clone(base.path, '.', ['--bare']);
|
||||||
tmpDir = await tmp.dir({ unsafeCleanup: true });
|
tmpDir = await tmp.dir({ unsafeCleanup: true });
|
||||||
await git.initRepo({
|
git.initRepo({
|
||||||
localDir: tmpDir.path,
|
localDir: tmpDir.path,
|
||||||
url: origin.path,
|
url: origin.path,
|
||||||
extraCloneOpts: {
|
extraCloneOpts: {
|
||||||
|
@ -100,10 +100,11 @@ describe('platform/git', () => {
|
||||||
const repo = Git(base.path).silent(true);
|
const repo = Git(base.path).silent(true);
|
||||||
await repo.submoduleAdd(base.path, 'submodule');
|
await repo.submoduleAdd(base.path, 'submodule');
|
||||||
await repo.commit('Add submodule');
|
await repo.commit('Add submodule');
|
||||||
await git.initRepo({
|
git.initRepo({
|
||||||
localDir: tmpDir.path,
|
localDir: tmpDir.path,
|
||||||
url: base.path,
|
url: base.path,
|
||||||
});
|
});
|
||||||
|
await git.syncGit();
|
||||||
expect(await fs.exists(tmpDir.path + '/.gitmodules')).toBeTruthy();
|
expect(await fs.exists(tmpDir.path + '/.gitmodules')).toBeTruthy();
|
||||||
expect(await git.getFileList()).toMatchSnapshot();
|
expect(await git.getFileList()).toMatchSnapshot();
|
||||||
await repo.reset(['--hard', 'HEAD^']);
|
await repo.reset(['--hard', 'HEAD^']);
|
||||||
|
@ -129,6 +130,7 @@ describe('platform/git', () => {
|
||||||
});
|
});
|
||||||
describe('isBranchStale()', () => {
|
describe('isBranchStale()', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
await git.syncGit();
|
||||||
await git.setBranch('master');
|
await git.setBranch('master');
|
||||||
});
|
});
|
||||||
it('should return false if same SHA as master', async () => {
|
it('should return false if same SHA as master', async () => {
|
||||||
|
@ -369,7 +371,7 @@ describe('platform/git', () => {
|
||||||
|
|
||||||
await git.setBranch('develop');
|
await git.setBranch('develop');
|
||||||
|
|
||||||
await git.initRepo({
|
git.initRepo({
|
||||||
localDir: tmpDir.path,
|
localDir: tmpDir.path,
|
||||||
url: base.path,
|
url: base.path,
|
||||||
});
|
});
|
||||||
|
@ -391,7 +393,7 @@ describe('platform/git', () => {
|
||||||
await repo.commit('past message2');
|
await repo.commit('past message2');
|
||||||
await repo.checkout('master');
|
await repo.checkout('master');
|
||||||
|
|
||||||
await git.initRepo({
|
git.initRepo({
|
||||||
localDir: tmpDir.path,
|
localDir: tmpDir.path,
|
||||||
url: base.path,
|
url: base.path,
|
||||||
});
|
});
|
||||||
|
@ -400,7 +402,7 @@ describe('platform/git', () => {
|
||||||
expect(await git.branchExists('renovate/test')).toBe(true);
|
expect(await git.branchExists('renovate/test')).toBe(true);
|
||||||
const cid = await git.getBranchCommit('renovate/test');
|
const cid = await git.getBranchCommit('renovate/test');
|
||||||
|
|
||||||
await git.initRepo({
|
git.initRepo({
|
||||||
localDir: tmpDir.path,
|
localDir: tmpDir.path,
|
||||||
url: base.path,
|
url: base.path,
|
||||||
});
|
});
|
||||||
|
@ -429,10 +431,11 @@ describe('platform/git', () => {
|
||||||
'test',
|
'test',
|
||||||
]);
|
]);
|
||||||
await repo.commit('Add submodule');
|
await repo.commit('Add submodule');
|
||||||
await git.initRepo({
|
git.initRepo({
|
||||||
localDir: tmpDir.path,
|
localDir: tmpDir.path,
|
||||||
url: base.path,
|
url: base.path,
|
||||||
});
|
});
|
||||||
|
await git.syncGit();
|
||||||
expect(await fs.exists(tmpDir.path + '/.gitmodules')).toBeTruthy();
|
expect(await fs.exists(tmpDir.path + '/.gitmodules')).toBeTruthy();
|
||||||
await repo.reset(['--hard', 'HEAD^']);
|
await repo.reset(['--hard', 'HEAD^']);
|
||||||
});
|
});
|
||||||
|
|
|
@ -114,6 +114,13 @@ let git: SimpleGit | undefined;
|
||||||
|
|
||||||
let privateKeySet = false;
|
let privateKeySet = false;
|
||||||
|
|
||||||
|
export function initRepo(args: StorageConfig): void {
|
||||||
|
config = { ...args } as any;
|
||||||
|
config.branchExists = {};
|
||||||
|
config.branchIsModified = {};
|
||||||
|
git = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
async function resetToBranch(branchName: string): Promise<void> {
|
async function resetToBranch(branchName: string): Promise<void> {
|
||||||
logger.debug(`resetToBranch(${branchName})`);
|
logger.debug(`resetToBranch(${branchName})`);
|
||||||
await git.raw(['reset', '--hard']);
|
await git.raw(['reset', '--hard']);
|
||||||
|
@ -143,14 +150,17 @@ async function cleanLocalBranches(): Promise<void> {
|
||||||
* By calling this function once the repo's branchPrefix is known, we can fetch all of Renovate's branches in one command.
|
* By calling this function once the repo's branchPrefix is known, we can fetch all of Renovate's branches in one command.
|
||||||
*/
|
*/
|
||||||
export async function setBranchPrefix(branchPrefix: string): Promise<void> {
|
export async function setBranchPrefix(branchPrefix: string): Promise<void> {
|
||||||
logger.debug('Setting branchPrefix: ' + branchPrefix);
|
|
||||||
config.branchPrefix = branchPrefix;
|
config.branchPrefix = branchPrefix;
|
||||||
const ref = `refs/heads/${branchPrefix}*:refs/remotes/origin/${branchPrefix}*`;
|
// If the repo is already cloned then set branchPrefix now, otherwise it will be called again during syncGit()
|
||||||
try {
|
if (git) {
|
||||||
await git.fetch(['origin', ref, '--depth=2', '--force']);
|
logger.debug('Setting branchPrefix: ' + branchPrefix);
|
||||||
} catch (err) /* istanbul ignore next */ {
|
const ref = `refs/heads/${branchPrefix}*:refs/remotes/origin/${branchPrefix}*`;
|
||||||
checkForPlatformFailure(err);
|
try {
|
||||||
throw err;
|
await git.fetch(['origin', ref, '--depth=2', '--force']);
|
||||||
|
} catch (err) /* istanbul ignore next */ {
|
||||||
|
checkForPlatformFailure(err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,20 +268,15 @@ export async function syncGit(): Promise<void> {
|
||||||
logger.debug({ err }, 'Error setting git author config');
|
logger.debug({ err }, 'Error setting git author config');
|
||||||
throw new Error(REPOSITORY_TEMPORARY_ERROR);
|
throw new Error(REPOSITORY_TEMPORARY_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
config.currentBranch = config.currentBranch || (await getDefaultBranch(git));
|
config.currentBranch = config.currentBranch || (await getDefaultBranch(git));
|
||||||
}
|
if (config.branchPrefix) {
|
||||||
|
await setBranchPrefix(config.branchPrefix);
|
||||||
export async function initRepo(args: StorageConfig): Promise<void> {
|
}
|
||||||
config = { ...args } as any;
|
|
||||||
config.branchExists = {};
|
|
||||||
config.branchIsModified = {};
|
|
||||||
git = undefined;
|
|
||||||
await syncGit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// istanbul ignore next
|
// istanbul ignore next
|
||||||
export function getRepoStatus(): Promise<StatusResult> {
|
export async function getRepoStatus(): Promise<StatusResult> {
|
||||||
|
await syncGit();
|
||||||
return git.status();
|
return git.status();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,6 +284,7 @@ export async function createBranch(
|
||||||
branchName: string,
|
branchName: string,
|
||||||
sha: string
|
sha: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
await syncGit();
|
||||||
logger.debug(`createBranch(${branchName})`);
|
logger.debug(`createBranch(${branchName})`);
|
||||||
await git.reset(ResetMode.HARD);
|
await git.reset(ResetMode.HARD);
|
||||||
await git.raw(['clean', '-fd']);
|
await git.raw(['clean', '-fd']);
|
||||||
|
@ -289,6 +295,7 @@ export async function createBranch(
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function branchExists(branchName: string): Promise<boolean> {
|
export async function branchExists(branchName: string): Promise<boolean> {
|
||||||
|
await syncGit();
|
||||||
// First check cache
|
// First check cache
|
||||||
if (config.branchExists[branchName] !== undefined) {
|
if (config.branchExists[branchName] !== undefined) {
|
||||||
return config.branchExists[branchName];
|
return config.branchExists[branchName];
|
||||||
|
@ -315,6 +322,7 @@ export async function branchExists(branchName: string): Promise<boolean> {
|
||||||
|
|
||||||
// Return the commit SHA for a branch
|
// Return the commit SHA for a branch
|
||||||
export async function getBranchCommit(branchName: string): Promise<string> {
|
export async function getBranchCommit(branchName: string): Promise<string> {
|
||||||
|
await syncGit();
|
||||||
if (!(await branchExists(branchName))) {
|
if (!(await branchExists(branchName))) {
|
||||||
throw Error(
|
throw Error(
|
||||||
'Cannot fetch commit for branch that does not exist: ' + branchName
|
'Cannot fetch commit for branch that does not exist: ' + branchName
|
||||||
|
@ -325,6 +333,7 @@ export async function getBranchCommit(branchName: string): Promise<string> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getCommitMessages(): Promise<string[]> {
|
export async function getCommitMessages(): Promise<string[]> {
|
||||||
|
await syncGit();
|
||||||
logger.debug('getCommitMessages');
|
logger.debug('getCommitMessages');
|
||||||
const res = await git.log({
|
const res = await git.log({
|
||||||
n: 10,
|
n: 10,
|
||||||
|
@ -334,6 +343,7 @@ export async function getCommitMessages(): Promise<string[]> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setBranch(branchName: string): Promise<string> {
|
export async function setBranch(branchName: string): Promise<string> {
|
||||||
|
await syncGit();
|
||||||
if (!(await branchExists(branchName))) {
|
if (!(await branchExists(branchName))) {
|
||||||
throwBranchValidationError(branchName);
|
throwBranchValidationError(branchName);
|
||||||
}
|
}
|
||||||
|
@ -365,6 +375,7 @@ export async function setBranch(branchName: string): Promise<string> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getFileList(): Promise<string[]> {
|
export async function getFileList(): Promise<string[]> {
|
||||||
|
await syncGit();
|
||||||
const branch = config.currentBranch;
|
const branch = config.currentBranch;
|
||||||
const submodules = await getSubmodules();
|
const submodules = await getSubmodules();
|
||||||
const files: string = await git.raw(['ls-tree', '-r', branch]);
|
const files: string = await git.raw(['ls-tree', '-r', branch]);
|
||||||
|
@ -385,6 +396,7 @@ export async function getFileList(): Promise<string[]> {
|
||||||
export async function getAllRenovateBranches(
|
export async function getAllRenovateBranches(
|
||||||
branchPrefix: string
|
branchPrefix: string
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
|
await syncGit();
|
||||||
const branches = await git.branch(['--remotes', '--verbose']);
|
const branches = await git.branch(['--remotes', '--verbose']);
|
||||||
return branches.all
|
return branches.all
|
||||||
.map(localName)
|
.map(localName)
|
||||||
|
@ -392,6 +404,7 @@ export async function getAllRenovateBranches(
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function isBranchStale(branchName: string): Promise<boolean> {
|
export async function isBranchStale(branchName: string): Promise<boolean> {
|
||||||
|
await syncGit();
|
||||||
if (!(await branchExists(branchName))) {
|
if (!(await branchExists(branchName))) {
|
||||||
throw Error(
|
throw Error(
|
||||||
'Cannot check staleness for branch that does not exist: ' + branchName
|
'Cannot check staleness for branch that does not exist: ' + branchName
|
||||||
|
@ -407,6 +420,7 @@ export async function isBranchStale(branchName: string): Promise<boolean> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function isBranchModified(branchName: string): Promise<boolean> {
|
export async function isBranchModified(branchName: string): Promise<boolean> {
|
||||||
|
await syncGit();
|
||||||
// First check cache
|
// First check cache
|
||||||
if (config.branchIsModified[branchName] !== undefined) {
|
if (config.branchIsModified[branchName] !== undefined) {
|
||||||
return config.branchIsModified[branchName];
|
return config.branchIsModified[branchName];
|
||||||
|
@ -438,6 +452,7 @@ export async function isBranchModified(branchName: string): Promise<boolean> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteBranch(branchName: string): Promise<void> {
|
export async function deleteBranch(branchName: string): Promise<void> {
|
||||||
|
await syncGit();
|
||||||
try {
|
try {
|
||||||
await git.raw(['push', '--delete', 'origin', branchName]);
|
await git.raw(['push', '--delete', 'origin', branchName]);
|
||||||
logger.debug({ branchName }, 'Deleted remote branch');
|
logger.debug({ branchName }, 'Deleted remote branch');
|
||||||
|
@ -457,6 +472,7 @@ export async function deleteBranch(branchName: string): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function mergeBranch(branchName: string): Promise<void> {
|
export async function mergeBranch(branchName: string): Promise<void> {
|
||||||
|
await syncGit();
|
||||||
await git.reset(ResetMode.HARD);
|
await git.reset(ResetMode.HARD);
|
||||||
await git.checkout(['-B', branchName, 'origin/' + branchName]);
|
await git.checkout(['-B', branchName, 'origin/' + branchName]);
|
||||||
await git.checkout(config.currentBranch);
|
await git.checkout(config.currentBranch);
|
||||||
|
@ -468,6 +484,7 @@ export async function mergeBranch(branchName: string): Promise<void> {
|
||||||
export async function getBranchLastCommitTime(
|
export async function getBranchLastCommitTime(
|
||||||
branchName: string
|
branchName: string
|
||||||
): Promise<Date> {
|
): Promise<Date> {
|
||||||
|
await syncGit();
|
||||||
try {
|
try {
|
||||||
const time = await git.show(['-s', '--format=%ai', 'origin/' + branchName]);
|
const time = await git.show(['-s', '--format=%ai', 'origin/' + branchName]);
|
||||||
return new Date(Date.parse(time));
|
return new Date(Date.parse(time));
|
||||||
|
@ -478,6 +495,7 @@ export async function getBranchLastCommitTime(
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getBranchFiles(branchName: string): Promise<string[]> {
|
export async function getBranchFiles(branchName: string): Promise<string[]> {
|
||||||
|
await syncGit();
|
||||||
try {
|
try {
|
||||||
const diff = await git.diffSummary([branchName, config.currentBranch]);
|
const diff = await git.diffSummary([branchName, config.currentBranch]);
|
||||||
return diff.files.map((file) => file.file);
|
return diff.files.map((file) => file.file);
|
||||||
|
@ -491,6 +509,7 @@ export async function getFile(
|
||||||
filePath: string,
|
filePath: string,
|
||||||
branchName?: string
|
branchName?: string
|
||||||
): Promise<string | null> {
|
): Promise<string | null> {
|
||||||
|
await syncGit();
|
||||||
if (branchName) {
|
if (branchName) {
|
||||||
const exists = await branchExists(branchName);
|
const exists = await branchExists(branchName);
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
|
@ -510,6 +529,7 @@ export async function getFile(
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function hasDiff(branchName: string): Promise<boolean> {
|
export async function hasDiff(branchName: string): Promise<boolean> {
|
||||||
|
await syncGit();
|
||||||
try {
|
try {
|
||||||
return (await git.diff(['HEAD', branchName])) !== '';
|
return (await git.diff(['HEAD', branchName])) !== '';
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -545,6 +565,7 @@ export async function commitFiles({
|
||||||
message,
|
message,
|
||||||
force = false,
|
force = false,
|
||||||
}: CommitFilesConfig): Promise<string | null> {
|
}: CommitFilesConfig): Promise<string | null> {
|
||||||
|
await syncGit();
|
||||||
logger.debug(`Committing files to branch ${branchName}`);
|
logger.debug(`Committing files to branch ${branchName}`);
|
||||||
if (!privateKeySet) {
|
if (!privateKeySet) {
|
||||||
await writePrivateKey(config.localDir);
|
await writePrivateKey(config.localDir);
|
||||||
|
|
Loading…
Reference in a new issue