add term
This commit is contained in:
241
static/term/pkg/axios/bin/contributors.js
Normal file
241
static/term/pkg/axios/bin/contributors.js
Normal file
@ -0,0 +1,241 @@
|
||||
import axios from "./githubAxios.js";
|
||||
import util from "util";
|
||||
import cp from "child_process";
|
||||
import Handlebars from "handlebars";
|
||||
import fs from "fs/promises";
|
||||
import {colorize} from "./helpers/colorize.js";
|
||||
|
||||
const exec = util.promisify(cp.exec);
|
||||
|
||||
const ONE_MB = 1024 * 1024;
|
||||
|
||||
const removeExtraLineBreaks = (str) => str.replace(/(?:\r\n|\r|\n){3,}/gm, '\r\n\r\n');
|
||||
|
||||
const cleanTemplate = template => template
|
||||
.replace(/\n +/g, '\n')
|
||||
.replace(/^ +/, '')
|
||||
.replace(/\n\n\n+/g, '\n\n')
|
||||
.replace(/\n\n$/, '\n');
|
||||
|
||||
const getUserFromCommit = ((commitCache) => async (sha) => {
|
||||
try {
|
||||
if(commitCache[sha] !== undefined) {
|
||||
return commitCache[sha];
|
||||
}
|
||||
|
||||
console.log(colorize()`fetch github commit info (${sha})`);
|
||||
|
||||
const {data} = await axios.get(`https://api.github.com/repos/axios/axios/commits/${sha}`);
|
||||
|
||||
return commitCache[sha] = {
|
||||
...data.commit.author,
|
||||
...data.author,
|
||||
avatar_url_sm: data.author.avatar_url ? data.author.avatar_url + '&s=18' : '',
|
||||
};
|
||||
} catch (err) {
|
||||
return commitCache[sha] = null;
|
||||
}
|
||||
})({});
|
||||
|
||||
const getIssueById = ((cache) => async (id) => {
|
||||
if(cache[id] !== undefined) {
|
||||
return cache[id];
|
||||
}
|
||||
|
||||
try {
|
||||
const {data} = await axios.get(`https://api.github.com/repos/axios/axios/issues/${id}`);
|
||||
|
||||
return cache[id] = data;
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
})({});
|
||||
|
||||
const getUserInfo = ((userCache) => async (userEntry) => {
|
||||
const {email, commits} = userEntry;
|
||||
|
||||
if (userCache[email] !== undefined) {
|
||||
return userCache[email];
|
||||
}
|
||||
|
||||
console.log(colorize()`fetch github user info [${userEntry.name}]`);
|
||||
|
||||
return userCache[email] = {
|
||||
...userEntry,
|
||||
...await getUserFromCommit(commits[0].hash)
|
||||
}
|
||||
})({});
|
||||
|
||||
const deduplicate = (authors) => {
|
||||
const loginsMap = {};
|
||||
const combined= {};
|
||||
|
||||
const assign = (a, b) => {
|
||||
const {insertions, deletions, points, ...rest} = b;
|
||||
|
||||
Object.assign(a, rest);
|
||||
|
||||
a.insertions += insertions;
|
||||
a.deletions += insertions;
|
||||
a.insertions += insertions;
|
||||
}
|
||||
|
||||
for(const [email, user] of Object.entries(authors)) {
|
||||
const {login} = user;
|
||||
let entry;
|
||||
|
||||
if(login && (entry = loginsMap[login])) {
|
||||
assign(entry, user);
|
||||
} else {
|
||||
login && (loginsMap[login] = user);
|
||||
combined[email] = user;
|
||||
}
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
const getReleaseInfo = ((releaseCache) => async (tag) => {
|
||||
if(releaseCache[tag] !== undefined) {
|
||||
return releaseCache[tag];
|
||||
}
|
||||
|
||||
const isUnreleasedTag = !tag;
|
||||
|
||||
const version = 'v' + tag.replace(/^v/, '');
|
||||
|
||||
const command = isUnreleasedTag ?
|
||||
`npx auto-changelog --unreleased-only --stdout --commit-limit false --template json` :
|
||||
`npx auto-changelog ${
|
||||
version ? '--starting-version ' + version + ' --ending-version ' + version : ''
|
||||
} --stdout --commit-limit false --template json`;
|
||||
|
||||
console.log(command);
|
||||
|
||||
const {stdout} = await exec(command, {maxBuffer: 10 * ONE_MB});
|
||||
|
||||
const release = JSON.parse(stdout)[0];
|
||||
|
||||
if(release) {
|
||||
const authors = {};
|
||||
|
||||
const commits = [
|
||||
...release.commits,
|
||||
...release.fixes.map(fix => fix.commit),
|
||||
...release.merges.map(fix => fix.commit)
|
||||
].filter(Boolean);
|
||||
|
||||
const commitMergeMap = {};
|
||||
|
||||
for(const merge of release.merges) {
|
||||
commitMergeMap[merge.commit.hash] = merge.id;
|
||||
}
|
||||
|
||||
for (const {hash, author, email, insertions, deletions} of commits) {
|
||||
const entry = authors[email] = (authors[email] || {
|
||||
name: author,
|
||||
prs: [],
|
||||
email,
|
||||
commits: [],
|
||||
insertions: 0, deletions: 0
|
||||
});
|
||||
|
||||
entry.commits.push({hash});
|
||||
|
||||
let pr;
|
||||
|
||||
if((pr = commitMergeMap[hash])) {
|
||||
entry.prs.push(pr);
|
||||
}
|
||||
|
||||
console.log(colorize()`Found commit [${hash}]`);
|
||||
|
||||
entry.displayName = entry.name || author || entry.login;
|
||||
|
||||
entry.github = entry.login ? `https://github.com/${encodeURIComponent(entry.login)}` : '';
|
||||
|
||||
entry.insertions += insertions;
|
||||
entry.deletions += deletions;
|
||||
entry.points = entry.insertions + entry.deletions;
|
||||
}
|
||||
|
||||
for (const [email, author] of Object.entries(authors)) {
|
||||
const entry = authors[email] = await getUserInfo(author);
|
||||
|
||||
entry.isBot = entry.type === "Bot";
|
||||
}
|
||||
|
||||
release.authors = Object.values(deduplicate(authors))
|
||||
.sort((a, b) => b.points - a.points);
|
||||
|
||||
release.allCommits = commits;
|
||||
}
|
||||
|
||||
releaseCache[tag] = release;
|
||||
|
||||
return release;
|
||||
})({});
|
||||
|
||||
const renderContributorsList = async (tag, template) => {
|
||||
const release = await getReleaseInfo(tag);
|
||||
|
||||
const compile = Handlebars.compile(String(await fs.readFile(template)))
|
||||
|
||||
const content = compile(release);
|
||||
|
||||
return removeExtraLineBreaks(cleanTemplate(content));
|
||||
}
|
||||
|
||||
const renderPRsList = async (tag, template, {comments_threshold= 5, awesome_threshold= 5, label = 'add_to_changelog'} = {}) => {
|
||||
const release = await getReleaseInfo(tag);
|
||||
|
||||
const prs = {};
|
||||
|
||||
for(const merge of release.merges) {
|
||||
const pr = await getIssueById(merge.id);
|
||||
|
||||
if (pr && pr.labels.find(({name})=> name === label)) {
|
||||
const {reactions, body} = pr;
|
||||
prs[pr.number] = pr;
|
||||
pr.isHot = pr.comments > comments_threshold;
|
||||
const points = reactions['+1'] +
|
||||
reactions['hooray'] + reactions['rocket'] + reactions['heart'] + reactions['laugh'] - reactions['-1'];
|
||||
|
||||
pr.isAwesome = points > awesome_threshold;
|
||||
|
||||
let match;
|
||||
|
||||
pr.messages = [];
|
||||
|
||||
if (body) {
|
||||
const reg = /```+changelog\n*(.+?)?\n*```/gms;
|
||||
|
||||
while((match = reg.exec(body))) {
|
||||
match[1] && pr.messages.push(match[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
release.prs = Object.values(prs);
|
||||
|
||||
const compile = Handlebars.compile(String(await fs.readFile(template)))
|
||||
|
||||
const content = compile(release);
|
||||
|
||||
return removeExtraLineBreaks(cleanTemplate(content));
|
||||
}
|
||||
|
||||
const getTagRef = async (tag) => {
|
||||
try {
|
||||
return (await exec(`git show-ref --tags "refs/tags/${tag}"`)).stdout.split(' ')[0];
|
||||
} catch(e) {
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
renderContributorsList,
|
||||
getReleaseInfo,
|
||||
renderPRsList,
|
||||
getTagRef
|
||||
}
|
Reference in New Issue
Block a user