1 | const fs = require('fs')
|
2 |
|
3 | const request = require('request')
|
4 | const ProgressBar = require('progress')
|
5 | const mkdirp = require('mkdirp')
|
6 | const checksum = require('checksum')
|
7 | const rimraf = require('rimraf')
|
8 | const tar = require('tar')
|
9 | const zlib = require('zlib')
|
10 |
|
11 | const config = require('./config')()
|
12 |
|
13 | function extract(source, callback) {
|
14 | const extractor = tar
|
15 | .extract({ cwd: config.outputPath })
|
16 | .on('error', function(error) {
|
17 | callback(error)
|
18 | })
|
19 | .on('end', function() {
|
20 | callback()
|
21 | })
|
22 |
|
23 | fs
|
24 | .createReadStream(source)
|
25 | .on('error', function(error) {
|
26 | callback(error)
|
27 | })
|
28 | .pipe(zlib.Gunzip())
|
29 | .pipe(extractor)
|
30 | }
|
31 |
|
32 | const verifyFile = function(file, callback) {
|
33 | checksum.file(file, { algorithm: 'sha256' }, (_, hash) => {
|
34 | const match = hash === config.checksum
|
35 |
|
36 | if (!match) {
|
37 | console.log(`Validation failed. Expected '${config.checksum}' but got '${hash}'`)
|
38 | }
|
39 |
|
40 | callback(match)
|
41 | })
|
42 | }
|
43 |
|
44 | const unpackFile = function(file) {
|
45 | extract(file, function(error) {
|
46 | if (error) {
|
47 | console.log('Unable to extract archive, aborting...', error)
|
48 | process.exit(1)
|
49 | }
|
50 | })
|
51 | }
|
52 |
|
53 | const downloadAndUnpack = () => {
|
54 | console.log(`Downloading Git from: ${config.source}`)
|
55 |
|
56 | const options = {
|
57 | url: config.source,
|
58 | headers: {
|
59 | Accept: 'application/octet-stream',
|
60 | 'User-Agent': 'dugite'
|
61 | },
|
62 | secureProtocol: 'TLSv1_2_method'
|
63 | }
|
64 |
|
65 | const req = request.get(options)
|
66 |
|
67 | req.pipe(fs.createWriteStream(config.tempFile))
|
68 |
|
69 | req.on('error', function(error) {
|
70 | if (error.code === 'ETIMEDOUT') {
|
71 | console.log(
|
72 | `A timeout has occurred while downloading '${config.source}' - check ` +
|
73 | `your internet connection and try again. If you are using a proxy, ` +
|
74 | `make sure that the HTTP_PROXY and HTTPS_PROXY environment variables are set.`,
|
75 | error
|
76 | )
|
77 | } else {
|
78 | console.log(`Error raised while downloading ${config.source}`, error)
|
79 | }
|
80 | process.exit(1)
|
81 | })
|
82 |
|
83 | req.on('response', function(res) {
|
84 | if (res.statusCode !== 200) {
|
85 | console.log(`Non-200 response returned from ${config.source} - (${res.statusCode})`)
|
86 | process.exit(1)
|
87 | }
|
88 |
|
89 | const len = parseInt(res.headers['content-length'], 10)
|
90 |
|
91 | console.log()
|
92 | const bar = new ProgressBar('Downloading Git [:bar] :percent :etas', {
|
93 | complete: '=',
|
94 | incomplete: ' ',
|
95 | width: 50,
|
96 | total: len
|
97 | })
|
98 |
|
99 | res.on('data', function(chunk) {
|
100 | bar.tick(chunk.length)
|
101 | })
|
102 |
|
103 | res.on('end', function() {
|
104 | console.log('\n')
|
105 |
|
106 | verifyFile(config.tempFile, valid => {
|
107 | if (valid) {
|
108 | unpackFile(config.tempFile)
|
109 | } else {
|
110 | console.log(`checksum verification failed, refusing to unpack...`)
|
111 | process.exit(1)
|
112 | }
|
113 | })
|
114 | })
|
115 | })
|
116 | }
|
117 |
|
118 | if (config.source === '') {
|
119 | console.log(
|
120 | `Skipping downloading embedded Git as platform '${process.platform}' is not supported.`
|
121 | )
|
122 | console.log(`To learn more about using dugite with a system Git: https://git.io/vF5oj`)
|
123 | process.exit(0)
|
124 | }
|
125 |
|
126 | if (fs.existsSync(config.outputPath)) {
|
127 | try {
|
128 | rimraf.sync(config.outputPath)
|
129 | } catch (err) {
|
130 | console.error(err)
|
131 | return
|
132 | }
|
133 | }
|
134 |
|
135 | mkdirp(config.outputPath, function(error) {
|
136 | if (error) {
|
137 | console.log(`Unable to create directory at ${config.outputPath}`, error)
|
138 | process.exit(1)
|
139 | }
|
140 |
|
141 | const tempFile = config.tempFile
|
142 |
|
143 | if (fs.existsSync(tempFile)) {
|
144 | verifyFile(tempFile, valid => {
|
145 | if (valid) {
|
146 | unpackFile(tempFile)
|
147 | } else {
|
148 | rimraf.sync(tempFile)
|
149 | downloadAndUnpack()
|
150 | }
|
151 | })
|
152 | return
|
153 | }
|
154 |
|
155 | downloadAndUnpack()
|
156 | })
|