diff --git a/lib/platform/azure/index.ts b/lib/platform/azure/index.ts index 51040110fb889bd4b9fd2a78f21c6bdc50a1e296..7f9b5c42d4d75d36d5ecdd7445cfc681b7b9a1a0 100644 --- a/lib/platform/azure/index.ts +++ b/lib/platform/azure/index.ts @@ -150,7 +150,7 @@ export async function initRepo({ const url = defaults.endpoint + `${encodeURIComponent(projectName)}/_git/${encodeURIComponent(repoName)}`; - await git.initRepo({ + git.initRepo({ ...config, localDir, url, diff --git a/lib/platform/bitbucket-server/index.ts b/lib/platform/bitbucket-server/index.ts index f2a7ab70d60ab2159a01e78d588105c8b49bb12a..f3ff7b8669bd8d1b1c434311aab69c328d6e8b95 100644 --- a/lib/platform/bitbucket-server/index.ts +++ b/lib/platform/bitbucket-server/index.ts @@ -179,7 +179,7 @@ export async function initRepo({ repository, }); - await git.initRepo({ + git.initRepo({ ...config, localDir, url: gitUrl, diff --git a/lib/platform/bitbucket/index.ts b/lib/platform/bitbucket/index.ts index 53b0cd12a2267d42e6bad7946172dbc1b2c90883..30ad14f102ec3c1612c9be236d98788833f59233 100644 --- a/lib/platform/bitbucket/index.ts +++ b/lib/platform/bitbucket/index.ts @@ -153,7 +153,7 @@ export async function initRepo({ repository, }); - await git.initRepo({ + git.initRepo({ ...config, localDir, url, diff --git a/lib/platform/gitea/index.ts b/lib/platform/gitea/index.ts index 081d1f20053dd71ce002276b8f4ee5c0df246500..fa4ab36f413515c440166961aae189dd253a5955 100644 --- a/lib/platform/gitea/index.ts +++ b/lib/platform/gitea/index.ts @@ -306,7 +306,7 @@ const platform: Platform = { gitEndpoint.auth = opts.token; // Initialize Git storage - await git.initRepo({ + git.initRepo({ ...config, url: URL.format(gitEndpoint), gitAuthorName: global.gitAuthor?.name, diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts index 09bb5a4af5b8f58eff51038a276047336bf4be3f..7d1ce6d5fe5136d7ba158084e7bb6b49066bc4f0 100644 --- a/lib/platform/github/index.ts +++ b/lib/platform/github/index.ts @@ -413,7 +413,7 @@ export async function initRepo({ ); parsedEndpoint.pathname = config.repository + '.git'; const url = URL.format(parsedEndpoint); - await git.initRepo({ + git.initRepo({ ...config, url, gitAuthorName: global.gitAuthor?.name, diff --git a/lib/platform/gitlab/index.ts b/lib/platform/gitlab/index.ts index 518cf5b3c00c4236b699b89b1eb757b370575ae7..19e511d6de334324b1c73c05fe80aac4b58c3ed2 100644 --- a/lib/platform/gitlab/index.ts +++ b/lib/platform/gitlab/index.ts @@ -224,7 +224,7 @@ export async function initRepo({ repoUrl.auth = 'oauth2:' + opts.token; url = URL.format(repoUrl); } - await git.initRepo({ + git.initRepo({ ...config, url, gitAuthorName: global.gitAuthor?.name, diff --git a/lib/util/git/index.spec.ts b/lib/util/git/index.spec.ts index 0a344739a728b5fea85097af556aac9b11de921d..4e31c3a31510f212871f4c96351a01d9c2aebad7 100644 --- a/lib/util/git/index.spec.ts +++ b/lib/util/git/index.spec.ts @@ -60,7 +60,7 @@ describe('platform/git', () => { const repo = Git(origin.path); await repo.clone(base.path, '.', ['--bare']); tmpDir = await tmp.dir({ unsafeCleanup: true }); - await git.initRepo({ + git.initRepo({ localDir: tmpDir.path, url: origin.path, extraCloneOpts: { @@ -100,10 +100,11 @@ describe('platform/git', () => { const repo = Git(base.path).silent(true); await repo.submoduleAdd(base.path, 'submodule'); await repo.commit('Add submodule'); - await git.initRepo({ + git.initRepo({ localDir: tmpDir.path, url: base.path, }); + await git.syncGit(); expect(await fs.exists(tmpDir.path + '/.gitmodules')).toBeTruthy(); expect(await git.getFileList()).toMatchSnapshot(); await repo.reset(['--hard', 'HEAD^']); @@ -129,6 +130,7 @@ describe('platform/git', () => { }); describe('isBranchStale()', () => { beforeEach(async () => { + await git.syncGit(); await git.setBranch('master'); }); it('should return false if same SHA as master', async () => { @@ -369,7 +371,7 @@ describe('platform/git', () => { await git.setBranch('develop'); - await git.initRepo({ + git.initRepo({ localDir: tmpDir.path, url: base.path, }); @@ -391,7 +393,7 @@ describe('platform/git', () => { await repo.commit('past message2'); await repo.checkout('master'); - await git.initRepo({ + git.initRepo({ localDir: tmpDir.path, url: base.path, }); @@ -400,7 +402,7 @@ describe('platform/git', () => { expect(await git.branchExists('renovate/test')).toBe(true); const cid = await git.getBranchCommit('renovate/test'); - await git.initRepo({ + git.initRepo({ localDir: tmpDir.path, url: base.path, }); @@ -429,10 +431,11 @@ describe('platform/git', () => { 'test', ]); await repo.commit('Add submodule'); - await git.initRepo({ + git.initRepo({ localDir: tmpDir.path, url: base.path, }); + await git.syncGit(); expect(await fs.exists(tmpDir.path + '/.gitmodules')).toBeTruthy(); await repo.reset(['--hard', 'HEAD^']); }); diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts index 3dafd524c794335b81aa7d3167995bdd254172fb..a2eb0bc6b1cbd47b4e09838c8d30439b12243b28 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -114,6 +114,13 @@ let git: SimpleGit | undefined; 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> { logger.debug(`resetToBranch(${branchName})`); 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. */ export async function setBranchPrefix(branchPrefix: string): Promise<void> { - logger.debug('Setting branchPrefix: ' + branchPrefix); config.branchPrefix = branchPrefix; - const ref = `refs/heads/${branchPrefix}*:refs/remotes/origin/${branchPrefix}*`; - try { - await git.fetch(['origin', ref, '--depth=2', '--force']); - } catch (err) /* istanbul ignore next */ { - checkForPlatformFailure(err); - throw err; + // If the repo is already cloned then set branchPrefix now, otherwise it will be called again during syncGit() + if (git) { + logger.debug('Setting branchPrefix: ' + branchPrefix); + const ref = `refs/heads/${branchPrefix}*:refs/remotes/origin/${branchPrefix}*`; + try { + 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'); throw new Error(REPOSITORY_TEMPORARY_ERROR); } - config.currentBranch = config.currentBranch || (await getDefaultBranch(git)); -} - -export async function initRepo(args: StorageConfig): Promise<void> { - config = { ...args } as any; - config.branchExists = {}; - config.branchIsModified = {}; - git = undefined; - await syncGit(); + if (config.branchPrefix) { + await setBranchPrefix(config.branchPrefix); + } } // istanbul ignore next -export function getRepoStatus(): Promise<StatusResult> { +export async function getRepoStatus(): Promise<StatusResult> { + await syncGit(); return git.status(); } @@ -279,6 +284,7 @@ export async function createBranch( branchName: string, sha: string ): Promise<void> { + await syncGit(); logger.debug(`createBranch(${branchName})`); await git.reset(ResetMode.HARD); await git.raw(['clean', '-fd']); @@ -289,6 +295,7 @@ export async function createBranch( } export async function branchExists(branchName: string): Promise<boolean> { + await syncGit(); // First check cache if (config.branchExists[branchName] !== undefined) { return config.branchExists[branchName]; @@ -315,6 +322,7 @@ export async function branchExists(branchName: string): Promise<boolean> { // Return the commit SHA for a branch export async function getBranchCommit(branchName: string): Promise<string> { + await syncGit(); if (!(await branchExists(branchName))) { throw Error( '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[]> { + await syncGit(); logger.debug('getCommitMessages'); const res = await git.log({ n: 10, @@ -334,6 +343,7 @@ export async function getCommitMessages(): Promise<string[]> { } export async function setBranch(branchName: string): Promise<string> { + await syncGit(); if (!(await branchExists(branchName))) { throwBranchValidationError(branchName); } @@ -365,6 +375,7 @@ export async function setBranch(branchName: string): Promise<string> { } export async function getFileList(): Promise<string[]> { + await syncGit(); const branch = config.currentBranch; const submodules = await getSubmodules(); const files: string = await git.raw(['ls-tree', '-r', branch]); @@ -385,6 +396,7 @@ export async function getFileList(): Promise<string[]> { export async function getAllRenovateBranches( branchPrefix: string ): Promise<string[]> { + await syncGit(); const branches = await git.branch(['--remotes', '--verbose']); return branches.all .map(localName) @@ -392,6 +404,7 @@ export async function getAllRenovateBranches( } export async function isBranchStale(branchName: string): Promise<boolean> { + await syncGit(); if (!(await branchExists(branchName))) { throw Error( '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> { + await syncGit(); // First check cache if (config.branchIsModified[branchName] !== undefined) { return config.branchIsModified[branchName]; @@ -438,6 +452,7 @@ export async function isBranchModified(branchName: string): Promise<boolean> { } export async function deleteBranch(branchName: string): Promise<void> { + await syncGit(); try { await git.raw(['push', '--delete', 'origin', branchName]); 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> { + await syncGit(); await git.reset(ResetMode.HARD); await git.checkout(['-B', branchName, 'origin/' + branchName]); await git.checkout(config.currentBranch); @@ -468,6 +484,7 @@ export async function mergeBranch(branchName: string): Promise<void> { export async function getBranchLastCommitTime( branchName: string ): Promise<Date> { + await syncGit(); try { const time = await git.show(['-s', '--format=%ai', 'origin/' + branchName]); return new Date(Date.parse(time)); @@ -478,6 +495,7 @@ export async function getBranchLastCommitTime( } export async function getBranchFiles(branchName: string): Promise<string[]> { + await syncGit(); try { const diff = await git.diffSummary([branchName, config.currentBranch]); return diff.files.map((file) => file.file); @@ -491,6 +509,7 @@ export async function getFile( filePath: string, branchName?: string ): Promise<string | null> { + await syncGit(); if (branchName) { const exists = await branchExists(branchName); if (!exists) { @@ -510,6 +529,7 @@ export async function getFile( } export async function hasDiff(branchName: string): Promise<boolean> { + await syncGit(); try { return (await git.diff(['HEAD', branchName])) !== ''; } catch (err) { @@ -545,6 +565,7 @@ export async function commitFiles({ message, force = false, }: CommitFilesConfig): Promise<string | null> { + await syncGit(); logger.debug(`Committing files to branch ${branchName}`); if (!privateKeySet) { await writePrivateKey(config.localDir);