runas-plugin-scm-git
Version:
Runas plugin for SCM operations (Git implementation)
279 lines (232 loc) • 6.94 kB
JavaScript
const fs = require('fs')
const path = require('path')
const async = require('async')
const _ = require('lodash')
const gitCmd = 'git'
const processDescriptor = (args, options) => {
return { cmd: gitCmd, args: args || [], options: options || {} }
}
const _scmDescriptors = {
add: (options) => {
return processDescriptor(['add', '--all', options.file ? options.file : '.'], { cwd: options.folder || '.' })
},
clone: (options) => {
const args = ['clone', options.repo].concat(options.args || [])
return processDescriptor(args, { cwd: options.folder || '.' })
},
commit: (options) => {
return processDescriptor(['commit', '-m', options.message || 'Initial commit', options.file ? options.file : '.'], { cwd: options.folder || '.' })
},
pull: (options) => {
const args = [ 'pull' ]
if (!options.simple) {
args.push('--rebase')
}
return processDescriptor(args, { cwd: options.folder || '.' })
},
fetch: (options) => {
return processDescriptor(['fetch', '-p'], { cwd: options.folder || '.' })
},
push: (options) => {
return processDescriptor(['push', '-u', 'origin', options.branch || 'master'], { cwd: options.folder || '.' })
},
checkout: (options) => {
const match = options.repo.match(/([^/]+)\.git$/)
const repoName = match ? match[1] : null
const repoFolder = path.join(options.folder, repoName)
const exists = fs.existsSync(repoFolder)
return exists
? _scmDescriptors.pull({ folder: repoFolder })
: _scmDescriptors.clone(options)
},
init: (options) => {
return processDescriptor([ 'init' ], { cwd: options.folder || '.' })
},
remoteAddOrigin: (options) => {
return processDescriptor(['remote', 'add', 'origin', options.repo], { cwd: options.folder || '.' })
},
config: (options) => {
const flags = options.global ? [ '--global' ] : []
const key = [ options.key ]
const value = [ options.value ]
const args = [ 'config' ].concat(flags).concat(key).concat(value)
return processDescriptor(args, { cwd: options.folder || '.' })
}
}
const _scmDescriptor = (operation) => _scmDescriptors[operation]
const _scmOperation = function(operation, options) {
const pd = _scmDescriptor(operation)(options)
return this.execute(pd.cmd, pd.args, pd.options)
}
/**
* options {
* repo: String,
* folder: String
* }
*/
const scmClone = function(options) {
return this._scmOperation('clone', options)
}
/**
* options {
* folder: String
* }
*/
const scmAdd = function(options) {
return this._scmOperation('add', options)
}
/**
* options {
* message: String,
* folder: String
* }
*/
const scmCommit = function(options) {
return this._scmOperation('commit', options)
}
/**
* options {
* folder: String
* }
*/
const scmPull = function(options) {
return this._scmOperation('pull', options)
}
const scmUpdate = scmPull
/**
* options {
* branch: String,
* folder: String
* }
*/
const scmPush = function(options) {
return this._scmOperation('push', options)
}
/**
* options {
* repo: String,
* folder: String
* }
*/
const scmCheckout = function(options) {
return this._scmOperation('checkout', options)
}
/**
* options {
* folder: String
* }
*/
const scmFetch = function(options) {
options = options ? options : {}
options.simple = true
return this._scmOperation('fetch', options)
.then(() => this.scmPull(options))
}
const scmGetBranch = function() {
if (!this.params.branch) {
const res = this.sh(`${gitCmd} branch --all`)
const lines = res.stdout.toString().split('\n')
let branch = lines.map((line) => line.startsWith('*') ? line : null).filter((e) => e !== null).pop()
this.params.branch = branch ? branch.replace('* ', '') : undefined
}
return this.params.branch
}
/**
* options {
* folder: String
* }
*/
const scmInit = function(options) {
return this._scmOperation('init', options)
}
/**
* options {
* repo: String
* folder: String
* }
*/
const scmRemoteAddOrigin = function(options) {
return this._scmOperation('remoteAddOrigin', options)
}
/**
* options {
* flags: Array<String>
* key: String
* value: String
* }
*/
const scmConfig = function(options) {
return this._scmOperation('config', options)
}
const scmGetSymbolicFullName = function(branch) {
const res = this.sh(`${gitCmd} rev-parse --symbolic-full-name ${branch}`)
const _err = res.stderr.toString()
return _err ? undefined : res.stdout.toString().trim()
}
const scmMassiveOperation = function(operation, repos) {
const descriptors = repos.map(repo => _scmDescriptor(operation)(repo))
const jobs = _.get(this, 'params.scm.jobs', 10)
return this.executeMassive(descriptors, jobs)
}
const _getError = function(repos, errors) {
let fail = ''
const process = (error) => {
const cmd = error.cmd
const args = error.args.join(' ')
let options = ''
_.keys(error.options).forEach(key => options += `[${key}]:${error.options[key]}`)
fail += `${cmd} ${args} ${options}\n`
if (error.error) {
const lines = error.error.split('\n')
lines.forEach(line => fail += (line + '\n'))
}
}
errors.forEach(error => process(error))
const errMsg = `${errors.length} operations failed`
this.logger.info('#green', `${repos.length - errors.length} operations OK`)
this.logger.info('#red', errMsg)
this.logger.info('#red', '\n' + fail)
return { error: errMsg, output: fail }
}
module.exports = {
config() {
const repos = _.get(this, 'params.scm.repos', false)
const operation = _.get(this, 'params.scm.operation', false)
const ignoreErrors = _.get(this, 'params.scm.ignoreErrors', false)
if (operation) {
return repos.length > 1
? this.scmMassiveOperation(operation, repos)
.then(() => this.logger.info('#green', `${repos.length} operations OK`))
.catch(errors => {
const _error = this._getError(repos, errors)
return ignoreErrors ? Promise.resolve() : Promise.reject(_error)
})
: this._scmOperation(operation, repos[0])
.then(() => this.logger.info('#green', 'operation OK'))
.catch(error => {
const _error = this._getError([ repos[0] ], [ error ])
return ignoreErrors ? Promise.resolve() : Promise.reject(_error)
})
}
},
addons: {
gitCmd: gitCmd,
_getError: _getError,
_scmOperation: _scmOperation,
scmClone: scmClone,
scmUpdate: scmUpdate,
scmCheckout: scmCheckout,
scmPull: scmPull,
scmFetch: scmFetch,
scmGetBranch: scmGetBranch,
scmGetSymbolicFullName: scmGetSymbolicFullName,
scmAdd: scmAdd,
scmCommit: scmCommit,
scmPush: scmPush,
scmInit: scmInit,
scmConfig: scmConfig,
scmRemoteAddOrigin: scmRemoteAddOrigin,
scmMassiveOperation: scmMassiveOperation
}
}