install.js 3.29 KB
'use strict'

const fs = require('fs')
const path = require('path')
const findParent = require('./utils/find-parent')
const findHooksDir = require('./utils/find-hooks-dir')
const getHookScript = require('./utils/get-hook-script')
const is = require('./utils/is')
const hooks = require('./hooks.json')

const SKIP = 'SKIP'
const UPDATE = 'UPDATE'
const MIGRATE_GHOOKS = 'MIGRATE_GHOOKS'
const MIGRATE_PRE_COMMIT = 'MIGRATE_PRE_COMMIT'
const CREATE = 'CREATE'

function write(filename, data) {
  fs.writeFileSync(filename, data)
  fs.chmodSync(filename, parseInt('0755', 8))
}

function createHook(depDir, projectDir, hooksDir, hookName, runnerPath) {
  const filename = path.join(hooksDir, hookName)

  let packageDir
  // prioritize package.json next to .git
  // this avoids double-install in lerna monorepos where both root and sub
  // package depends on this module
  if (fs.existsSync(path.join(projectDir, 'package.json'))) {
    packageDir = projectDir
  } else {
    packageDir = findParent(depDir, 'package.json')
  }

  // In order to support projects with package.json in a different directory
  // than .git, find relative path from project directory to package.json
  const relativePath = path.join('.', path.relative(projectDir, packageDir))

  const hookScript = getHookScript(hookName, relativePath, runnerPath)

  // Create hooks directory if needed
  if (!fs.existsSync(hooksDir)) fs.mkdirSync(hooksDir)

  if (!fs.existsSync(filename)) {
    write(filename, hookScript)
    return CREATE
  }

  if (is.ghooks(filename)) {
    write(filename, hookScript)
    return MIGRATE_GHOOKS
  }

  if (is.preCommit(filename)) {
    write(filename, hookScript)
    return MIGRATE_PRE_COMMIT
  }

  if (is.huskyOrYorkie(filename)) {
    write(filename, hookScript)
    return UPDATE
  }

  return SKIP
}

function installFrom(depDir) {
  try {
    const isInSubNodeModule = (depDir.match(/node_modules/g) || []).length > 1
    if (isInSubNodeModule) {
      return console.log(
        "trying to install from sub 'node_module' directory,",
        'skipping Git hooks installation'
      )
    }

    const projectDir = findParent(depDir, 'package.json')
    const hooksDir = findHooksDir(projectDir)
    const runnerPath = './node_modules/yorkie/src/runner.js'

    if (hooksDir) {
      hooks
        .map(function(hookName) {
          return {
            hookName: hookName,
            action: createHook(depDir, projectDir, hooksDir, hookName, runnerPath)
          }
        })
        .forEach(function(item) {
          switch (item.action) {
            case MIGRATE_GHOOKS:
              console.log(`migrating existing ghooks ${item.hookName} script`)
              break
            case MIGRATE_PRE_COMMIT:
              console.log(
                `migrating existing pre-commit ${item.hookName} script`
              )
              break
            case UPDATE:
              break
            case SKIP:
              console.log(`skipping ${item.hookName} hook (existing user hook)`)
              break
            case CREATE:
              break
            default:
              console.error('Unknown action')
          }
        })
      console.log('done\n')
    } else {
      console.log("can't find .git directory, skipping Git hooks installation")
    }
  } catch (e) {
    console.error(e)
  }
}

module.exports = installFrom