{"version":3,"sources":["jsdelivr-header.js","/npm/git-tally@1.2.1/index.js"],"names":[],"mappings":"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","file":"/npm/git-tally@1.2.1/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/git-tally@1.2.1/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","#!/usr/bin/env node\n\nconst program = require('commander');\nconst fs = require('fs');\nconst path = require('path');\nconst child_process = require('child_process');\nconst colors = require('colors');\nconst Table = require('cli-table');\nconst json2csv = require('json2csv');\n\nconst testGitPromise = (pathOrGit) => {\n  return new Promise((resolve, reject) => {\n    const testGit = child_process.spawn('git', ['status'], { cwd: pathOrGit });\n\n    testGit.on('error', (code) => {\n      console.log('Not a git repository.'.red);\n      process.exit(1);\n    });\n\n    testGit.on('close', (code) => {\n      if (0 !== code) {\n        console.log('Not a git repository.'.red);\n        process.exit(1);\n      }\n\n      resolve();\n    });\n  });\n}\n\nconst statsPromise = (pathOrGit) => {\n  return new Promise((resolve, reject) => {\n    let statsString = '';\n\n    const stats = child_process.spawn('git', ['log', '--numstat', '--pretty=format:@@@COMMIT@@@<%an> <%ae> <%at>@', '--no-merges'], { cwd: pathOrGit });\n\n    stats.stdout.on('data', (data) => {\n      statsString += data.toString();\n    });\n\n    stats.stderr.on('data', (data) => {\n      console.log(data.toString());\n    });\n\n    stats.on('close', (code) => {\n      if (0 !== code) {\n        console.log('Git stats failed'.red);\n        process.exit(1);\n      }\n\n      resolve(statsString);\n    });\n  });\n}\n\nconst cloneToTemp = (address) => {\n  return new Promise((resolve, reject) => {\n    const tmpDir = 'tmp-repo' + Date.now();\n\n    const clone = child_process.spawn('git', ['clone', address, tmpDir]);\n\n    clone.on('close', (code) => {\n      if (0 !== code) {\n        console.log('Git clone failed'.red);\n        process.exit(1);\n      }\n\n      const onClose = () => {\n        fs.rmdirSync(path.resolve('./' + tmpDir), { recursive: true });\n      };\n\n      process.on('exit', onClose);\n      process.on('SIGINT', onClose);\n\n      resolve(tmpDir);\n    });\n  });\n}\n\nconst run = async (pathOrGitHub, options) => {\n\n  let workingDir = '.';\n\n  if (pathOrGitHub) {\n    workingDir = pathOrGitHub;\n  }\n\n  if (workingDir.match(/(https?:|git@github)/i)) {\n    workingDir = './' + await cloneToTemp(workingDir);\n  }\n\n  workingDir = path.resolve(workingDir);\n\n  await testGitPromise(workingDir);\n\n  let statsString = await statsPromise(workingDir);\n  const tally = {};\n\n  const commits = statsString.split('@@@COMMIT@@');\n\n  commits.forEach((commit) => {\n    lines = commit.split(\"\\n\");\n\n    if (1 > lines.length || !lines[0].match(/^@<.*?> <.*?> <.*?>@$/)) {\n      return;\n    }\n\n    let name = lines[0].replace(/^@<(.*?)> <.*?> <.*?>@$/, '$1');\n    let email = lines[0].replace(/^@<.*?> <(.*?)> <.*?>@$/, '$1');\n    let date = lines[0].replace(/^@<.*?> <.*?> <(.*?)>@$/, '$1');\n\n    if (!email && options.requireEmail) {\n      return;\n    }\n\n    let key = name + ' ' + email;\n\n    if (!tally[key]) {\n      tally[key] = {\n        name: name,\n        email: email,\n        added: 0,\n        removed: 0,\n        latestCommit: date,\n      };\n    }\n\n    if (date > tally[key].latestCommit) {\n      tally[key].latestCommit = date;\n    }\n\n    lines.shift();\n\n    lines.forEach((line) => {\n      if (!line.match(/^[0-9]+\\t[0-9]+\\t.*$/)) {\n        return;\n      }\n\n      let added = line.replace(/^([0-9]+)\\t[0-9]+\\t.*$/, '$1');\n      let removed = line.replace(/^[0-9]+\\t([0-9]+)\\t.*$/, '$1');\n\n      tally[key].added += parseInt(added);\n      tally[key].removed += parseInt(removed);\n    });\n  });\n\n  if (Object.keys(tally).length < 1) {\n    console.log('No authors found.'.red);\n    process.exit(1);\n  }\n\n  let orderedTally = [];\n\n  /**\n   * Sort\n   */\n  for (author in tally) {\n    let inserted = false;\n\n    for (let i = 0; i < orderedTally.length; i++) {\n      if (tally[author].added + tally[author].removed >= orderedTally[i].added + orderedTally[i].removed) {\n        orderedTally.splice(i, 0, tally[author]);\n        inserted = true;\n        break;\n      }\n    }\n\n    if (!inserted) {\n      orderedTally.push(tally[author]);\n    }\n  }\n\n  if (options.asc) {\n    orderedTally = orderedTally.reverse();\n  }\n\n  if (options.emailOnly) {\n    orderedTally.forEach((author) => {\n      console.log(author.email);\n    });\n  } else {\n    const table = new Table({\n      head: ['Name', 'Email', 'Added', 'Removed', 'Latest Commit']\n    });\n\n    orderedTally.forEach((author) => {\n      let date = new Date(author.latestCommit * 1000);\n      author.latestCommit = date.toString();\n      table.push(Object.keys(author).map((key) => author[key]));\n    });\n\n    console.log(table.toString());\n  }\n\n  if (options.csvOutput) {\n    let fields = ['name', 'email'];\n\n    if (options.emailOnly) {\n      fields = ['email'];\n    }\n\n    const csv = json2csv({ data: orderedTally, fields: ['name', 'email'] });\n\n    console.log(options.csvOutput);\n\n    if (true === options.csvOutput) {\n      options.csvOutput = 'output.csv'\n    }\n\n    fs.writeFile(options.csvOutput, csv, function(err) {\n      if (err) {\n        throw err;\n      }\n\n      console.log(('csv saved to ' + options.csvOutput).green);\n    });\n  }\n}\n\n(async () => {\n  program\n    .version('1.0.0')\n    .arguments('[path-or-github-repo]', 'Can be a path or a GitHub repository URL')\n    .option('--email-only', 'Only output email')\n    .option('--asc', 'Show results in ascending order')\n    .option('--csv-output [value]', 'Save data to csv file. output.csv by default.')\n    .action(run);\n\n  await program.parseAsync(process.argv);\n})();\n"]}