1 | const downloadUrl = require('download')
|
2 | const gitclone = require('git-clone')
|
3 | const rm = require('rimraf').sync
|
4 | const logger = require('./logger')
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | module.exports = download
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | function download(repo, dest, opts, fn) {
|
22 | console.log(
|
23 | `
|
24 | ${repo}
|
25 | `
|
26 | )
|
27 | if (typeof opts === 'function') {
|
28 | fn = opts
|
29 | opts = null
|
30 | }
|
31 | opts = opts || {}
|
32 | const clone = opts.clone || false
|
33 | const gitServer = opts.gitServer || false
|
34 |
|
35 | if (gitServer) {
|
36 | repo = normalize(`direct:${gitServer}${clone ? ':' : '/'}${repo}`, clone)
|
37 | } else {
|
38 | repo = normalize(repo, clone)
|
39 | }
|
40 |
|
41 | logger.debug('repo', repo)
|
42 |
|
43 | if (clone) {
|
44 | gitclone(repo.url, dest, { checkout: repo.checkout, shallow: repo.checkout === 'master' }, err => {
|
45 | if (err === undefined) {
|
46 | rm(dest + '/.git')
|
47 | fn()
|
48 | } else {
|
49 | fn(err)
|
50 | }
|
51 | })
|
52 | } else {
|
53 | downloadUrl(repo.url, dest, { extract: true, strip: 1, mode: '666', headers: { accept: 'application/zip' } })
|
54 | .then(() => {
|
55 | fn()
|
56 | })
|
57 | .catch(err => {
|
58 | fn(err)
|
59 | })
|
60 | }
|
61 | }
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 | function normalize(repo, clone) {
|
71 | let regex = /^(?:(direct):([^#]+)(?:#(.+))?)$/
|
72 | let match = regex.exec(repo)
|
73 |
|
74 | if (match) {
|
75 | let url = match[2]
|
76 | const checkout = match[3] || 'master'
|
77 |
|
78 | if (clone) {
|
79 | url = url.replace(/^(f|ht)tps?:\/\//, '')
|
80 | url = 'git@' + url + '.git'
|
81 | }
|
82 | return {
|
83 | type: 'direct',
|
84 | url,
|
85 | checkout
|
86 | }
|
87 | }
|
88 | regex = /^(?:(github|gitlab|bitbucket):)?(?:(.+):)?([^/]+)\/([^#]+)(?:#(.+))?$/
|
89 | match = regex.exec(repo)
|
90 | const type = match[1] || 'github'
|
91 | let origin = match[2] || null
|
92 | const owner = match[3]
|
93 | const name = match[4]
|
94 | const checkout = match[5] || 'master'
|
95 |
|
96 | if (origin === null) {
|
97 | if (type === 'github') {
|
98 | origin = 'github.com'
|
99 | } else if (type === 'gitlab') {
|
100 | origin = 'gitlab.com'
|
101 | } else if (type === 'bitbucket') {
|
102 | origin = 'bitbucket.com'
|
103 | }
|
104 | }
|
105 |
|
106 | const nRepo = {
|
107 | type,
|
108 | origin,
|
109 | owner,
|
110 | name,
|
111 | checkout
|
112 | }
|
113 |
|
114 | nRepo.url = getUrl(nRepo, clone)
|
115 | return nRepo
|
116 | }
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 | function addProtocol(origin, clone) {
|
126 | if (!/^(f|ht)tps?:\/\//i.test(origin)) {
|
127 | if (clone) {
|
128 | origin = 'git@' + origin
|
129 | } else {
|
130 | origin = 'https://' + origin
|
131 | }
|
132 | }
|
133 |
|
134 | return origin
|
135 | }
|
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 | function getUrl(repo, clone) {
|
145 | let url
|
146 |
|
147 |
|
148 | let origin = addProtocol(repo.origin, clone)
|
149 | if (/^git@/i.test(origin)) {
|
150 | origin += ':'
|
151 | } else {
|
152 | origin += '/'
|
153 | }
|
154 |
|
155 |
|
156 | if (clone) {
|
157 | url = origin + repo.owner + '/' + repo.name + '.git'
|
158 | } else if (repo.type === 'github') {
|
159 | url = origin + repo.owner + '/' + repo.name + '/archive/' + repo.checkout + '.zip'
|
160 | } else if (repo.type === 'gitlab') {
|
161 | url = origin + repo.owner + '/' + repo.name + '/repository/archive.zip?ref=' + repo.checkout
|
162 | } else if (repo.type === 'bitbucket') {
|
163 | url = origin + repo.owner + '/' + repo.name + '/get/' + repo.checkout + '.zip'
|
164 | }
|
165 |
|
166 | return url
|
167 | }
|