repos.js

import util from 'util';
import childProcess from 'child_process'
const exec = util.promisify(childProcess.exec);
import darcsConfig from '../darcsconfig.js'
import xmlJs from 'xml-js'
import { getDiffsFromPatchText } from '../helpers.js'

let repos = null

export default async () => {
  if (repos === null) {
    repos = await Promise.all(Object.keys(darcsConfig.repos).map(async (repoName) => {
      const branchNames = Object.keys(darcsConfig.repos[repoName].branches)
      const branches = await Promise.all(branchNames.map(async (branchName) => {
        const repoLocation = darcsConfig.repos[repoName].branches[branchName].location
        const filesRes = await exec(`(cd ${repoLocation}; darcs show files)`)
        const files = filesRes.stdout.split("\n").filter(item => item.length > 0 && item != ".")

        const patches = new Map()
        const totalPatchesCountRes = await exec(`(cd ${repoLocation}; darcs log --count)`)
        const totalPatchesCount = parseInt(totalPatchesCountRes.stdout)
        let hunkRegex = RegExp(/^ *hunk /)

        // Get 100 patches at a time and parse those
        for (let i = 1; i <= totalPatchesCount; i = i + 100) {
          let patchesSubset = await exec(`(cd ${repoLocation}; darcs log --index=${i}-${i+100} -v)`)
          patchesSubset = patchesSubset.stdout.split("\n")
          do {
            const nextPatchStart = patchesSubset.findIndex((line, index) => {
              return index > 0 && line.startsWith("patch ")
            })
            const currentPatch = patchesSubset.slice(0, nextPatchStart - 1)
            patchesSubset = patchesSubset.slice(nextPatchStart)

            const hash = currentPatch[0].replace("patch ", "").trim()
            const author = currentPatch[1].replace("Author: ", "").trim()
            const date = currentPatch[2].replace("Date: ", "").trim()
            const name = currentPatch[3].replace("  * ", "").trim()
            const diffStart = currentPatch.findIndex((line) => {
              return line.match(hunkRegex)
            })
            const description = currentPatch.slice(5, diffStart).map(str => str.replace("  ", "")).join("\n").trim()

            const diffs = getDiffsFromPatchText(currentPatch.slice(diffStart).map(str => str.trimStart()).join("\n"))
            patches.set(hash, {
              name,
              description,
              author,
              date,
              hash,
              diffs,
            })
          } while (patchesSubset.length > 1)
        }

        const info = {
          files,
          patches: [...patches.values()],
        }

        return [branchName, info]
      }))

      const branchObject = {}
      branches.forEach((branch) => {
        branchObject[branch[0]] = branch[1]
      })
      return [repoName, branchObject]
    }))

    const reposObject = {}
    repos.forEach((repo) => {
      reposObject[repo[0]] = repo[1]
    })

    repos = reposObject
  }

  return repos
}