forked from wangbo/easyai
perf(release): 复用分支补丁核对并固定比较快照
This commit is contained in:
@@ -42,6 +42,15 @@ export function inspectRepository(repository, { fetch = false } = {}) {
|
||||
const output = git(repository.path, 'for-each-ref', '--format=%(refname)%00%(objectname)%00%(symref)', `refs/remotes/${remote}/`);
|
||||
const cache = new Map();
|
||||
const knownEquivalent = new Set();
|
||||
const mergeBases = new Map();
|
||||
const isolatedEquivalence = new Map();
|
||||
const mergeBase = sha => {
|
||||
if (!mergeBases.has(sha)) {
|
||||
try { mergeBases.set(sha, git(repository.path, 'merge-base', result.targetSha, sha)); }
|
||||
catch (error) { if (error.status === 1 && !String(error.stderr || '').trim()) mergeBases.set(sha, null); else throw error; }
|
||||
}
|
||||
return mergeBases.get(sha);
|
||||
};
|
||||
for (const line of output.split('\n').filter(Boolean)) {
|
||||
const [ref, sha, symbolicRef] = line.split('\0');
|
||||
if (symbolicRef || ref === targetRef) continue;
|
||||
@@ -49,20 +58,24 @@ export function inspectRepository(repository, { fetch = false } = {}) {
|
||||
try {
|
||||
let comparison = cache.get(sha);
|
||||
if (!comparison) {
|
||||
const range = `${targetRef}..${ref}`;
|
||||
// Pin the inventory SHAs so another fetch cannot change this comparison midway.
|
||||
const range = `${result.targetSha}..${sha}`;
|
||||
const ahead = Number(git(repository.path, 'rev-list', '--count', range));
|
||||
comparison = { ahead, unmergedCommits: [], equivalentCommits: [], mergeCommits: [] };
|
||||
if (ahead > 0) {
|
||||
const cherry = git(repository.path, 'cherry', targetRef, ref);
|
||||
const cherry = git(repository.path, 'cherry', result.targetSha, sha);
|
||||
const equivalence = new Map(cherry.split('\n').filter(Boolean).map(line => [line.slice(2), line[0]]));
|
||||
comparison.mergeCommits = commits(repository.path, range, '--merges');
|
||||
for (const commit of commits(repository.path, range, '--no-merges')) {
|
||||
if (equivalence.get(commit.sha) === '-') knownEquivalent.add(commit.sha);
|
||||
// If the branch merged the target, Git's merge base can hide older
|
||||
// upstream patches. Compare the individual incoming commit too.
|
||||
if (comparison.mergeCommits.length && !knownEquivalent.has(commit.sha)) {
|
||||
const isolated = git(repository.path, 'cherry', targetRef, commit.sha);
|
||||
for (const line of isolated.split('\n')) if (line.startsWith('- ')) knownEquivalent.add(line.slice(2));
|
||||
if (comparison.mergeCommits.length && !knownEquivalent.has(commit.sha) && mergeBase(sha) !== mergeBase(commit.sha)) {
|
||||
if (!isolatedEquivalence.has(commit.sha)) {
|
||||
const isolated = git(repository.path, 'cherry', result.targetSha, commit.sha);
|
||||
isolatedEquivalence.set(commit.sha, isolated.split('\n').includes('- ' + commit.sha));
|
||||
}
|
||||
if (isolatedEquivalence.get(commit.sha)) knownEquivalent.add(commit.sha);
|
||||
}
|
||||
// A changed SHA alone does not mean the change is absent from the target branch.
|
||||
const list = knownEquivalent.has(commit.sha) ? comparison.equivalentCommits : comparison.unmergedCommits;
|
||||
|
||||
Reference in New Issue
Block a user