Skip to content

Commit

Permalink
feat: use isBranchBehindBase cached result (#16595)
Browse files Browse the repository at this point in the history
  • Loading branch information
RahulGautamSingh authored Jul 21, 2022
1 parent 5b74dad commit 93707c1
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 1 deletion.
40 changes: 40 additions & 0 deletions lib/util/git/behind-base-branch-cache.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { mocked } from '../../../test/util';
import * as _repositoryCache from '../cache/repository';
import type { BranchCache, RepoCacheData } from '../cache/repository/types';
import { getCachedBehindBaseResult } from './behind-base-branch-cache';

jest.mock('../cache/repository');
const repositoryCache = mocked(_repositoryCache);

describe('util/git/behind-base-branch-cache', () => {
let repoCache: RepoCacheData = {};

beforeEach(() => {
repoCache = {};
repositoryCache.getCache.mockReturnValue(repoCache);
});

describe('getCachedBehindBaseResult', () => {
it('returns null if cache is not populated', () => {
expect(getCachedBehindBaseResult('foo', '111')).toBeNull();
});

it('returns null if branch not found', () => {
expect(getCachedBehindBaseResult('foo', '111')).toBeNull();
});

it('returns true if target SHA has changed', () => {
repoCache.branches = [
{ branchName: 'foo', sha: 'aaa', parentSha: '222' } as BranchCache,
];
expect(getCachedBehindBaseResult('foo', '111')).toBeTrue();
});

it('returns false if target SHA has not changed', () => {
repoCache.branches = [
{ branchName: 'foo', sha: 'aaa', parentSha: '111' } as BranchCache,
];
expect(getCachedBehindBaseResult('foo', '111')).toBeFalse();
});
});
});
20 changes: 20 additions & 0 deletions lib/util/git/behind-base-branch-cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { getCache } from '../cache/repository';

// Compare cached parent Sha of a branch to the fetched base-branch sha to determine whether the branch is behind the base
// Since cache is updated after each run, this will be sufficient to determine whether a branch is behind its parent.
export function getCachedBehindBaseResult(
branchName: string,
currentBaseBranchSha: string
): boolean | null {
const cache = getCache();
const { branches = [] } = cache;
const cachedBranch = branches?.find(
(branch) => branch.branchName === branchName
);

if (!cachedBranch) {
return null;
}

return currentBaseBranchSha !== cachedBranch.parentSha;
}
15 changes: 15 additions & 0 deletions lib/util/git/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
CONFIG_VALIDATION,
INVALID_PATH,
} from '../../constants/error-messages';
import * as _repoCache from '../cache/repository';
import type { BranchCache } from '../cache/repository/types';
import { newlineRegex, regEx } from '../regex';
import * as _conflictsCache from './conflicts-cache';
import * as _modifiedCache from './modified-cache';
Expand All @@ -17,6 +19,8 @@ import { setNoVerify } from '.';
jest.mock('./conflicts-cache');
jest.mock('./modified-cache');
jest.mock('delay');
jest.mock('../cache/repository');
const repoCache = mocked(_repoCache);
const conflictsCache = mocked(_conflictsCache);
const modifiedCache = mocked(_modifiedCache);

Expand Down Expand Up @@ -239,16 +243,27 @@ describe('util/git/index', () => {

describe('isBranchBehindBase()', () => {
it('should return false if same SHA as master', async () => {
repoCache.getCache.mockReturnValueOnce({});
expect(
await git.isBranchBehindBase('renovate/future_branch')
).toBeFalse();
});

it('should return true if SHA different from master', async () => {
repoCache.getCache.mockReturnValueOnce({});
expect(await git.isBranchBehindBase('renovate/past_branch')).toBeTrue();
});

it('should return result even if non-default and not under branchPrefix', async () => {
const parentSha = await git.getBranchParentSha('develop');
repoCache.getCache.mockReturnValueOnce({}).mockReturnValueOnce({
branches: [
{
branchName: 'develop',
parentSha: parentSha,
} as BranchCache,
],
});
expect(await git.isBranchBehindBase('develop')).toBeTrue();
expect(await git.isBranchBehindBase('develop')).toBeTrue(); // cache
});
Expand Down
10 changes: 9 additions & 1 deletion lib/util/git/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type { GitProtocol } from '../../types/git';
import { Limit, incLimitedValue } from '../../workers/global/limits';
import { newlineRegex, regEx } from '../regex';
import { parseGitAuthor } from './author';
import { getCachedBehindBaseResult } from './behind-base-branch-cache';
import { getNoVerify, simpleGitConfig } from './config';
import {
getCachedConflictResult,
Expand Down Expand Up @@ -550,6 +551,13 @@ export function getBranchList(): string[] {
}

export async function isBranchBehindBase(branchName: string): Promise<boolean> {
const { currentBranchSha } = config;

let isBehind = getCachedBehindBaseResult(branchName, currentBranchSha);
if (isBehind !== null) {
return isBehind;
}

await syncGit();
try {
const { currentBranchSha, currentBranch } = config;
Expand All @@ -559,7 +567,7 @@ export async function isBranchBehindBase(branchName: string): Promise<boolean> {
'--contains',
config.currentBranchSha,
]);
const isBehind = !branches.all.map(localName).includes(branchName);
isBehind = !branches.all.map(localName).includes(branchName);
logger.debug(
{ isBehind, currentBranch, currentBranchSha },
`isBranchBehindBase=${isBehind}`
Expand Down

0 comments on commit 93707c1

Please sign in to comment.