diff --git a/source/plugins/languages/analyzers.mjs b/source/plugins/languages/analyzers.mjs index 3dd2b2f5..9ef532eb 100644 --- a/source/plugins/languages/analyzers.mjs +++ b/source/plugins/languages/analyzers.mjs @@ -5,7 +5,7 @@ export async function indepth({login, data, imports, repositories}, {skipped}) { throw new Error("Feature requires github-linguist") //Compute repositories stats from fetched repositories - const results = {total:0, lines:{}, stats:{}} + const results = {total:0, lines:{}, stats:{}, commits:0, files:0, missed:0} for (const repository of repositories) { //Skip repository if asked if ((skipped.includes(repository.name.toLocaleLowerCase())) || (skipped.includes(`${repository.owner.login}/${repository.name}`.toLocaleLowerCase()))) { @@ -52,7 +52,7 @@ export async function recent({login, data, imports, rest, account}, {skipped = [ //Get user recent activity console.debug(`metrics/compute/${login}/plugins > languages > querying api`) - const commits = [], pages = Math.ceil(load/100), results = {total:0, lines:{}, stats:{}, commits:0, files:0, days} + const commits = [], pages = Math.ceil(load/100), results = {total:0, lines:{}, stats:{}, commits:0, files:0, missed:0, days} try { for (let page = 1; page <= pages; page++) { console.debug(`metrics/compute/${login}/plugins > languages > loading page ${page}`) @@ -68,7 +68,6 @@ export async function recent({login, data, imports, rest, account}, {skipped = [ console.debug(`metrics/compute/${login}/plugins > languages > no more page to load`) } console.debug(`metrics/compute/${login}/plugins > languages > ${commits.length} commits loaded`) - results.commits = commits.length results.latest = Math.round((new Date().getTime() - new Date(commits.slice(-1).shift()?.created_at).getTime()) / (1000 * 60 * 60 * 24)) //Retrieve edited files and filter edited lines (those starting with +/-) from patches @@ -91,7 +90,6 @@ export async function recent({login, data, imports, rest, account}, {skipped = [ //Temporary directory const path = imports.paths.join(imports.os.tmpdir(), `${data.user.databaseId}-${tempdir}`) console.debug(`metrics/compute/${login}/plugins > languages > creating temp dir ${path} with ${patches.length} files`) - results.files = patches.length //Process try { @@ -125,6 +123,9 @@ export async function recent({login, data, imports, rest, account}, {skipped = [ //Analyze repository await analyze(arguments[0], {results, path:imports.paths.join(path, directory)}) + + //Since we reproduce a "partial repository" with a single commit, use number of commits retrieved instead + results.commits = commits.length } } catch { @@ -146,10 +147,11 @@ async function analyze({login, imports, data}, {results, path}) { //Processing diff const per_page = 1 + const edited = new Set() console.debug(`metrics/compute/${login}/plugins > languages > indepth > checking git log`) for (let page = 0; ; page++) { try { - const stdout = await imports.run(`git log ${data.shared["commits.authoring"].map(authoring => `--author="${authoring}"`).join(" ")} --regexp-ignore-case --format="" --patch --max-count=${per_page} --skip=${page*per_page}`, {cwd:path}, {log:false}) + const stdout = await imports.run(`git log ${data.shared["commits.authoring"].map(authoring => `--author="${authoring}"`).join(" ")} --regexp-ignore-case --format=short --patch --max-count=${per_page} --skip=${page*per_page}`, {cwd:path}, {log:false}) let file = null, lang = null if (!stdout.trim().length) { console.debug(`metrics/compute/${login}/plugins > languages > indepth > no more commits`) @@ -157,6 +159,11 @@ async function analyze({login, imports, data}, {results, path}) { } console.debug(`metrics/compute/${login}/plugins > languages > indepth > processing commits ${page*per_page} from ${(page+1)*per_page}`) for (const line of stdout.split("\n").map(line => line.trim())) { + //Commits counter + if (/^commit [0-9a-f]{40}$/.test(line)) { + results.commits++ + continue + } //Ignore empty lines or unneeded lines if ((!/^[+]/.test(line))||(!line.length)) continue @@ -164,6 +171,7 @@ async function analyze({login, imports, data}, {results, path}) { if (/^[+]{3}\sb[/](?[\s\S]+)$/.test(line)) { file = line.match(/^[+]{3}\sb[/](?[\s\S]+)$/)?.groups?.file ?? null lang = files[file] ?? null + edited.add(file) continue } //Ignore unkonwn languages @@ -180,9 +188,10 @@ async function analyze({login, imports, data}, {results, path}) { } catch { console.debug(`metrics/compute/${login}/plugins > languages > indepth > an error occured on page ${page}, skipping...`) + results.missed += per_page } } - + results.files += edited.size } //import.meta.main @@ -201,7 +210,7 @@ if (/languages.analyzers.mjs$/.test(process.argv[1])) { //Prepare call const imports = await import("../../app/metrics/utils.mjs") - const results = {total:0, lines:{}, stats:{}} + const results = {total:0, lines:{}, stats:{}, missed:0} console.debug = log => /exited with code null/.test(log) ? console.error(log.replace(/^.*--max-count=(?\d+) --skip=(?\d+).*$/, (_, step, start) => `error: skipped commits ${start} from ${Number(start)+Number(step)}`)) : null //Analyze repository diff --git a/source/plugins/languages/index.mjs b/source/plugins/languages/index.mjs index 62a95669..26247df5 100644 --- a/source/plugins/languages/index.mjs +++ b/source/plugins/languages/index.mjs @@ -38,7 +38,7 @@ export default async function({login, data, imports, q, rest, account}, {enabled //Iterate through user's repositories and retrieve languages data console.debug(`metrics/compute/${login}/plugins > languages > processing ${data.user.repositories.nodes.length} repositories`) - const languages = {unique, sections, details, colors:{}, total:0, stats:{}, "stats.recent":{}} + const languages = {unique, sections, details, indepth, colors:{}, total:0, stats:{}, "stats.recent":{}} for (const repository of data.user.repositories.nodes) { //Skip repository if asked if ((skipped.includes(repository.name.toLocaleLowerCase())) || (skipped.includes(`${repository.owner.login}/${repository.name}`.toLocaleLowerCase()))) { @@ -63,6 +63,7 @@ export default async function({login, data, imports, q, rest, account}, {enabled if (indepth) { console.debug(`metrics/compute/${login}/plugins > languages > switching to indepth mode (this may take some time)`) Object.assign(languages, await indepth_analyzer({login, data, imports, repositories}, {skipped})) + console.log(`metrics/compute/${login}/plugins > languages > indepth analysis missed ${languages.missed} commits`) } //Compute languages stats @@ -79,7 +80,6 @@ export default async function({login, data, imports, q, rest, account}, {enabled } } -console.log(aliases) //Apply aliases for (const section of ["favorites", "recent"]) { for (const language of languages[section]) { diff --git a/source/templates/classic/partials/languages.ejs b/source/templates/classic/partials/languages.ejs index 98c7a1d9..b2d672aa 100644 --- a/source/templates/classic/partials/languages.ejs +++ b/source/templates/classic/partials/languages.ejs @@ -22,6 +22,10 @@ estimation from <%= plugins.languages["stats.recent"]?.files %> edited file<%= s(plugins.languages["stats.recent"]?.files) %> from <%= plugins.languages["stats.recent"]?.commits %> commit<%= s(plugins.languages["stats.recent"]?.commits) %> over last <%= plugins.languages["stats.recent"]?.latest ?? plugins.languages["stats.recent"]?.days %> day<%= s(plugins.languages["stats.recent"]?.latest ?? plugins.languages["stats.recent"]?.days) %> + <% } else if ((section === "most-used")&&(plugins.languages.indepth)) { %> + + estimation from <%= plugins.languages.files %> edited file<%= s(plugins.languages.files) %> from <%= plugins.languages.commits %> commit<%= s(plugins.languages.commits) %> + <% } %>