UNPKG

clone-repo

Version:

使用node提取git仓库的下载工具,支持 GitHub,Gitee,GitLab,Bitbucket。

161 lines (143 loc) 3.48 kB
const downloadUrl = require('download') const gitclone = require('git-clone') const rm = require('rimraf').sync /** * Download `repo` to `dest` and callback `fn(err)`. * * @param {String} repo * @param {String} dest * @param {Object} opts */ function download(repo, dest, opts = {}) { return new Promise((resolve, reject) => { let clone = opts.clone || false delete opts.clone repo = normalize(repo) let url = repo.url || getUrl(repo, clone) if (clone) { const cloneOptions = { checkout: repo.checkout, shallow: repo.checkout === 'master', ...opts } gitclone(url, dest, cloneOptions, err => { if (err === undefined) { rm(dest + '/.git') resolve() } else { reject(err) } }) } else { const downloadOptions = { extract: true, strip: 1, mode: '666', ...opts, headers: { accept: 'application/zip', ...(opts.headers || {}) } } downloadUrl(url, dest, downloadOptions).then(() => { resolve() }).catch(err => { reject(err) }) } }) } /** * Normalize a repo string. * * @param {String} repo * @return {Object} */ function normalize(repo) { let regex = /^(?:(direct):([^#]+)(?:#(.+))?)$/ const match = regex.exec(repo) if (match) { const url = match[2] let directCheckout = match[3] || 'master' return { type: 'direct', url, checkout: directCheckout } } else { regex = /^(?:(github|gitlab|bitbucket|gitee):)?(?:(.+):)?([^/]+)\/([^#]+)(?:#(.+))?$/ match = regex.exec(repo) let type = match[1] || 'github' let origin = match[2] || null const owner = match[3] const name = match[4] let checkout = match[5] || 'master' if (origin == null) { if (type === 'github') { origin = 'github.com' } else if (type === 'gitlab') { origin = 'gitlab.com' } else if (type === 'bitbucket') { origin = 'bitbucket.org' } else if (type === 'gitee') { origin = 'gitee.com' } } return { type, origin, owner, name, checkout } } } /** * Adds protocol to url in none specified * * @param {String} url * @return {String} */ function addProtocol(origin, clone) { if (!/^(f|ht)tps?:\/\//i.test(origin)) { if (clone) { origin = 'git@' + origin } else { origin = 'https://' + origin } } return origin } /** * Return a zip or git url for a given `repo`. * * @param {Object} repo * @return {String} */ function getUrl(repo, clone) { let url // Get origin with protocol and add trailing slash or colon (for ssh) let origin = addProtocol(repo.origin, clone) if (/^git@/i.test(origin)) { origin = origin + ':' } else { origin = origin + '/' } // Build url if (clone) { url = origin + repo.owner + '/' + repo.name + '.git' } else { if (repo.type === 'github') { url = origin + repo.owner + '/' + repo.name + '/archive/' + repo.checkout + '.zip' } else if (repo.type === 'gitlab') { url = origin + repo.owner + '/' + repo.name + '/repository/archive.zip?ref=' + repo.checkout } else if (repo.type === 'bitbucket') { url = origin + repo.owner + '/' + repo.name + '/get/' + repo.checkout + '.zip' } } return url } /** * Expose `download`. */ module.exports = download