index.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. var downloadUrl = require('download')
  2. var gitclone = require('git-clone')
  3. var rm = require('rimraf').sync
  4. /**
  5. * Expose `download`.
  6. */
  7. module.exports = download
  8. /**
  9. * Download `repo` to `dest` and callback `fn(err)`.
  10. *
  11. * @param {String} repo
  12. * @param {String} dest
  13. * @param {Object} opts
  14. * @param {Function} fn
  15. */
  16. function download (repo, dest, opts, fn) {
  17. if (typeof opts === 'function') {
  18. fn = opts
  19. opts = null
  20. }
  21. opts = opts || {}
  22. var clone = opts.clone || false
  23. repo = normalize(repo)
  24. var url = repo.url || getUrl(repo, clone)
  25. if (clone) {
  26. gitclone(url, dest, { checkout: repo.checkout, shallow: repo.checkout === 'master' }, function (err) {
  27. if (err === undefined) {
  28. rm(dest + '/.git')
  29. fn()
  30. } else {
  31. fn(err)
  32. }
  33. })
  34. } else {
  35. downloadUrl(url, dest, { extract: true, strip: 1, mode: '666', headers: { accept: 'application/zip' } })
  36. .then(function (data) {
  37. fn()
  38. })
  39. .catch(function (err) {
  40. fn(err)
  41. })
  42. }
  43. }
  44. /**
  45. * Normalize a repo string.
  46. *
  47. * @param {String} repo
  48. * @return {Object}
  49. */
  50. function normalize (repo) {
  51. var regex = /^(?:(direct):([^#]+)(?:#(.+))?)$/
  52. var match = regex.exec(repo)
  53. if (match) {
  54. var url = match[2]
  55. var checkout = match[3] || 'master'
  56. return {
  57. type: 'direct',
  58. url: url,
  59. checkout: checkout
  60. }
  61. } else {
  62. regex = /^(?:(github|gitlab|bitbucket):)?(?:(.+):)?([^\/]+)\/([^#]+)(?:#(.+))?$/
  63. match = regex.exec(repo)
  64. var type = match[1] || 'github'
  65. var origin = match[2] || null
  66. var owner = match[3]
  67. var name = match[4]
  68. var checkout = match[5] || 'master'
  69. if (origin == null) {
  70. if (type === 'github')
  71. origin = 'github.com'
  72. else if (type === 'gitlab')
  73. origin = 'gitlab.com'
  74. else if (type === 'bitbucket')
  75. origin = 'bitbucket.com'
  76. }
  77. return {
  78. type: type,
  79. origin: origin,
  80. owner: owner,
  81. name: name,
  82. checkout: checkout
  83. }
  84. }
  85. }
  86. /**
  87. * Adds protocol to url in none specified
  88. *
  89. * @param {String} url
  90. * @return {String}
  91. */
  92. function addProtocol (origin, clone) {
  93. if (!/^(f|ht)tps?:\/\//i.test(origin)) {
  94. if (clone)
  95. origin = 'git@' + origin
  96. else
  97. origin = 'https://' + origin
  98. }
  99. return origin
  100. }
  101. /**
  102. * Return a zip or git url for a given `repo`.
  103. *
  104. * @param {Object} repo
  105. * @return {String}
  106. */
  107. function getUrl (repo, clone) {
  108. var url
  109. // Get origin with protocol and add trailing slash or colon (for ssh)
  110. var origin = addProtocol(repo.origin, clone)
  111. if (/^git\@/i.test(origin))
  112. origin = origin + ':'
  113. else
  114. origin = origin + '/'
  115. // Build url
  116. if (clone) {
  117. url = origin + repo.owner + '/' + repo.name + '.git'
  118. } else {
  119. if (repo.type === 'github')
  120. url = origin + repo.owner + '/' + repo.name + '/archive/' + repo.checkout + '.zip'
  121. else if (repo.type === 'gitlab')
  122. url = origin + repo.owner + '/' + repo.name + '/repository/archive.zip?ref=' + repo.checkout
  123. else if (repo.type === 'bitbucket')
  124. url = origin + repo.owner + '/' + repo.name + '/get/' + repo.checkout + '.zip'
  125. }
  126. return url
  127. }