+// ---------------------------------------------------------------------------
+
+type SemVersion = { major: number, minor: number, patch: number }
+function parseSemVersion (s: string) {
+ const parsed = s.match(/^v?(\d+)\.(\d+)\.(\d+)$/i)
+
+ return {
+ major: parseInt(parsed[1]),
+ minor: parseInt(parsed[2]),
+ patch: parseInt(parsed[3])
+ } as SemVersion
+}
+
+// ---------------------------------------------------------------------------
+
+function execShell (command: string, options?: ExecOptions) {
+ return new Promise<{ err?: Error, stdout: string, stderr: string }>((res, rej) => {
+ exec(command, options, (err, stdout, stderr) => {
+ // eslint-disable-next-line prefer-promise-reject-errors
+ if (err) return rej({ err, stdout, stderr })