From 8fcde964181791d4c119d5aa63be4ee8925a6e4f Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sun, 18 Jul 2021 21:30:03 -0700 Subject: [PATCH] tools: use mailmap for find-inactive-collaborators The current version of find-inactive-collaborators can generate a false positive if the mailmap entry for a collaborator does not match the entry in the README. (We should probably lint or otherwise check for that sort of mismatch but regardless, it is relatively easy to avoid having find-inactive-collaborators tripped up by it, so let's fix that too, which is this commit.) --- tools/find-inactive-collaborators.mjs | 42 ++++++++++++++++++--------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/tools/find-inactive-collaborators.mjs b/tools/find-inactive-collaborators.mjs index 2951d81c534696..a89f29c324f28d 100755 --- a/tools/find-inactive-collaborators.mjs +++ b/tools/find-inactive-collaborators.mjs @@ -22,27 +22,33 @@ async function runGitCommand(cmd, mapFn) { const errorHandler = new Promise( (_, reject) => childProcess.on('error', reject) ); - const returnedSet = new Set(); + let returnValue = mapFn ? new Set() : ''; await Promise.race([errorHandler, Promise.resolve()]); + // If no mapFn, return the value. If there is a mapFn, use it to make a Set to + // return. for await (const line of lines) { await Promise.race([errorHandler, Promise.resolve()]); - const val = mapFn(line); - if (val) { - returnedSet.add(val); + if (mapFn) { + const val = mapFn(line); + if (val) { + returnValue.add(val); + } + } else { + returnValue += line; } } - return Promise.race([errorHandler, Promise.resolve(returnedSet)]); + return Promise.race([errorHandler, Promise.resolve(returnValue)]); } // Get all commit authors during the time period. const authors = await runGitCommand( - `git shortlog -n -s --max-count="${SINCE}" HEAD`, + `git shortlog -n -s --email --max-count="${SINCE}" HEAD`, (line) => line.trim().split('\t', 2)[1] ); // Get all commit landers during the time period. const landers = await runGitCommand( - `git shortlog -n -s -c --max-count="${SINCE}" HEAD`, + `git shortlog -n -s -c --email --max-count="${SINCE}" HEAD`, (line) => line.trim().split('\t', 2)[1] ); @@ -52,7 +58,7 @@ const approvingReviewers = await runGitCommand( (line) => /^ Reviewed-By: ([^<]+)/.exec(line)[1].trim() ); -async function retrieveCollaboratorsFromReadme() { +async function getCollaboratorsFromReadme() { const readmeText = readline.createInterface({ input: fs.createReadStream(new URL('../README.md', import.meta.url)), crlfDelay: Infinity, @@ -69,14 +75,22 @@ async function retrieveCollaboratorsFromReadme() { break; } if (line.startsWith('**') && isCollaborator) { - returnedArray.push(line.split('**', 2)[1].trim()); + const [_, name, email] = /^\*\*([^*]+)\*\* <(.+)>/.exec(line); + const mailmap = await runGitCommand( + `git check-mailmap '${name} <${email}>'` + ); + returnedArray.push({ + name, + email, + mailmap, + }); } } return returnedArray; } // Get list of current collaborators from README.md. -const collaborators = await retrieveCollaboratorsFromReadme(); +const collaborators = await getCollaboratorsFromReadme(); console.log(`In the last ${SINCE} commits:\n`); console.log(`* ${authors.size.toLocaleString()} authors have made commits.`); @@ -85,10 +99,10 @@ console.log(`* ${approvingReviewers.size.toLocaleString()} reviewers have approv console.log(`* ${collaborators.length.toLocaleString()} collaborators currently in the project.`); const inactive = collaborators.filter((collaborator) => - !authors.has(collaborator) && - !landers.has(collaborator) && - !approvingReviewers.has(collaborator) -); + !authors.has(collaborator.mailmap) && + !landers.has(collaborator.mailmap) && + !approvingReviewers.has(collaborator.name) +).map((collaborator) => collaborator.name); if (inactive.length) { console.log('\nInactive collaborators:\n');