Passed
Push — develop ( 30a60d...9e20cf )
by Bjarn
03:01 queued 52s
created

CustomTool.install   A

Complexity

Conditions 3

Size

Total Lines 24
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 22
dl 0
loc 24
rs 9.352
c 0
b 0
f 0
1
import execa from 'execa'
2
import * as fs from 'fs'
3
import {chmodSync, existsSync, unlinkSync} from 'fs'
4
import {error, info, success} from '../utils/console'
5
import Tool from './tool'
6
7
abstract class CustomTool extends Tool {
8
9
    abstract name: string
10
    abstract alias: string
11
12
    abstract url: string
13
    abstract shasum: string
14
15
    binLocation = '/usr/local/bin'
16
17
    /**
18
     * Install the binary.
19
     */
20
    install = async (): Promise<boolean> => {
21
        if (await this.isInstalled()) {
22
            error(`${this.name} already is installed. Execute it by running ${this.alias}`)
23
            return false
24
        }
25
26
        const fileName = this.url.substring(this.url.lastIndexOf('/') + 1)
27
28
        info(`Downloading binary for ${this.name}...`)
29
30
        await execa('curl', ['-OL', this.url], {cwd: '/tmp/'})
31
32
        if (!(await this.isValidShasum(`/tmp/${fileName}`))) {
33
            error(`Unable to install ${this.name}. The checksum ${this.shasum} is not equal to the one of the downloaded file.`)
34
            await unlinkSync(`/tmp/${fileName}`)
35
            return false
36
        }
37
38
        await fs.copyFileSync(`/tmp/${fileName}`, `${this.binLocation}/${this.alias}`)
39
        await chmodSync(`${this.binLocation}/${this.alias}`, 0o777)
40
41
        success(`Successfully installed ${this.name}.`)
42
43
        return true
44
    }
45
46
    /**
47
     * Uninstall the binary
48
     */
49
    uninstall = async (): Promise<boolean> => {
50
        if (!(await this.isInstalled())) {
51
            error(`${this.name} is not installed`)
52
            return false
53
        }
54
55
        info(`Uninstalling ${this.name}...`)
56
57
        try {
58
            await unlinkSync(`${this.binLocation}/${this.alias}`)
59
        } catch (e) {
60
            throw new Error(`Unable to uninstall ${this.name}. Please remove the file manually to continue:\nrm${this.binLocation}/${this.alias}`)
61
        }
62
63
        success(`Uninstalled ${this.name}.`)
64
65
        return true
66
    }
67
68
    /**
69
     * Check if the binary of the app exists.
70
     */
71
    isInstalled = async (): Promise<boolean> => {
72
        return existsSync(`${this.binLocation}/${this.alias}`)
73
    }
74
75
    /**
76
     * Check if the file has a valid shasum.
77
     *
78
     * @param path
79
     */
80
    isValidShasum = async (path: string): Promise<boolean> => {
81
        const {stdout} = await execa('shasum', ['-a256', path])
82
        const shasum = stdout.replace(path, '').trim()
83
84
        return shasum === this.shasum
85
    }
86
87
}
88
89
export default CustomTool