forked from pascalgn/automerge-action
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
199 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,13 @@ class ExitError extends Error { | |
|
||
const FETCH_DEPTH = 10; | ||
|
||
const COMMON_ARGS = [ | ||
"-c", | ||
"user.name=GitHub", | ||
"-c", | ||
"[email protected]" | ||
]; | ||
|
||
function git(cwd, ...args) { | ||
const stdio = [ | ||
"ignore", | ||
|
@@ -23,7 +30,11 @@ function git(cwd, ...args) { | |
: `git ${args.join(" ")}`; | ||
logger.debug("Executing", command); | ||
return new Promise((resolve, reject) => { | ||
const proc = spawn("git", args.filter(a => a !== null), { cwd, stdio }); | ||
const proc = spawn( | ||
"git", | ||
COMMON_ARGS.concat(args.filter(a => a !== null)), | ||
{ cwd, stdio } | ||
); | ||
const buffers = []; | ||
proc.stdout.on("data", data => buffers.push(data)); | ||
proc.on("error", () => { | ||
|
@@ -72,10 +83,33 @@ async function fetch(dir, branch) { | |
|
||
async function fetchUntilMergeBase(dir, branch, timeout) { | ||
const maxTime = new Date().getTime() + timeout; | ||
const ref = `refs/remotes/origin/${branch}`; | ||
while (new Date().getTime() < maxTime) { | ||
const base = await mergeBase(dir, branch); | ||
const base = await mergeBase(dir, "HEAD", ref); | ||
if (base) { | ||
return base; | ||
const bases = [base]; | ||
const parents = await mergeCommits(dir, ref); | ||
let fetchMore = false; | ||
for (const parent of parents.flat()) { | ||
const b = await mergeBase(dir, parent, ref); | ||
if (b) { | ||
if (!bases.includes(b)) { | ||
bases.push(b); | ||
} | ||
} else { | ||
// we found a commit which does not have a common ancestor with | ||
// the branch we want to merge, so we need to fetch more | ||
fetchMore = true; | ||
break; | ||
} | ||
} | ||
if (!fetchMore) { | ||
const commonBase = await mergeBase(dir, ...bases); | ||
if (!commonBase) { | ||
throw new Error(`failed to find common base for ${bases}`); | ||
} | ||
return commonBase; | ||
} | ||
} | ||
await fetchDeepen(dir); | ||
} | ||
|
@@ -86,14 +120,19 @@ async function fetchDeepen(dir) { | |
await git(dir, "fetch", "--quiet", "--deepen", FETCH_DEPTH); | ||
} | ||
|
||
async function mergeBase(dir, branch) { | ||
async function mergeBase(dir, ...refs) { | ||
if (refs.length === 1) { | ||
return refs[0]; | ||
} else if (refs.length < 1) { | ||
throw new Error("empty refs!"); | ||
} | ||
let todo = refs; | ||
try { | ||
return await git( | ||
dir, | ||
"merge-base", | ||
"HEAD", | ||
`refs/remotes/origin/${branch}` | ||
); | ||
while (todo.length > 1) { | ||
const base = await git(dir, "merge-base", todo[0], todo[1]); | ||
todo = [base].concat(todo.slice(2)); | ||
} | ||
return todo[0]; | ||
} catch (e) { | ||
if (e instanceof ExitError && e.code === 1) { | ||
return null; | ||
|
@@ -103,6 +142,13 @@ async function mergeBase(dir, branch) { | |
} | ||
} | ||
|
||
async function mergeCommits(dir, ref) { | ||
return (await git(dir, "rev-list", "--parents", `${ref}..HEAD`)) | ||
.split(/\n/g) | ||
.map(line => line.split(/ /g).slice(1)) | ||
.filter(commit => commit.length > 1); | ||
} | ||
|
||
async function head(dir) { | ||
return await git(dir, "show-ref", "--head", "-s", "/HEAD"); | ||
} | ||
|
@@ -134,6 +180,7 @@ module.exports = { | |
fetchUntilMergeBase, | ||
fetchDeepen, | ||
mergeBase, | ||
mergeCommits, | ||
head, | ||
sha, | ||
rebase, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters