diff --git a/src/handlers.ts b/src/handlers.ts index a8fbd0f..c6ccf22 100644 --- a/src/handlers.ts +++ b/src/handlers.ts @@ -1,9 +1,10 @@ -import axios from 'axios' -import { Writer } from 'clitastic' -import { unlinkSync } from 'fs' +import { chmodSync, renameSync, unlinkSync } from 'fs' import { tmpdir } from 'os' import { join, resolve } from 'path' +import axios from 'axios' +import { Writer } from 'clitastic' + import { config, INSTALL_DIR, VERSION } from './autorestic' import { checkAndConfigureBackends, getBackendsFromLocations, getEnvFromBackend } from './backend' import { backupAll } from './backup' @@ -147,7 +148,7 @@ const handlers: Handlers = { checkIfResticIsAvailable() console.log('Restic is already installed') return - } catch (e) { + } catch { } const w = new Writer('Checking latest version... ⏳') @@ -164,9 +165,7 @@ const handlers: Handlers = { } w.replaceLn('Downloading binary... 🌎') - const name = `${json.name.replace(' ', '_')}_${process.platform}_${ - archMap[process.arch] - }.bz2` + const name = `${json.name.replace(' ', '_')}_${process.platform}_${archMap[process.arch]}.bz2` const dl = json.assets.find((asset: any) => asset.name === name) if (!dl) return console.log( @@ -184,8 +183,8 @@ const handlers: Handlers = { unlinkSync(tmp) w.replaceLn(`Moving to ${INSTALL_DIR} 🚙`) - exec('chmod', ['+x', extracted]) - exec('mv', [extracted, INSTALL_DIR + '/restic']) + chmodSync(extracted, 0o755) + renameSync(extracted, INSTALL_DIR + '/restic') w.done( `\nFinished! restic is installed under: ${INSTALL_DIR}`.underline + ' 🎉', diff --git a/src/utils.ts b/src/utils.ts index 4f34c8c..8d3b7bb 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,8 +1,8 @@ import { spawnSync, SpawnSyncOptions } from 'child_process' import { randomBytes } from 'crypto' -import { createWriteStream } from 'fs' +import { createWriteStream, unlinkSync, renameSync } from 'fs' import { dirname, isAbsolute, join, resolve } from 'path' -import { homedir } from 'os' +import { homedir, tmpdir } from 'os' import axios from 'axios' import { Duration, Humanizer } from 'uhrwerk' @@ -44,13 +44,14 @@ export const execPlain = (command: string, opt: SpawnSyncOptions = {}) => { export const checkIfResticIsAvailable = () => checkIfCommandIsAvailable( 'restic', - 'Restic is not installed'.red + - ' https://restic.readthedocs.io/en/latest/020_installation.html#stable-releases', + 'restic is not installed'.red + + '\nEither run ' + 'autorestic install'.green + + '\nOr go to https://restic.readthedocs.io/en/latest/020_installation.html#stable-releases', ) export const checkIfCommandIsAvailable = (cmd: string, errorMsg?: string) => { - if (require('child_process').spawnSync(cmd).error) - throw new Error(errorMsg ? errorMsg : `"${errorMsg}" is not installed`.red) + if (spawnSync(cmd).error) + throw new Error(errorMsg ? errorMsg : `"${cmd}" is not installed`.red) } export const makeObjectKeysLowercase = (object: Object): any => @@ -83,11 +84,19 @@ export const downloadFile = async (url: string, to: string) => responseType: 'stream', }) - const stream = createWriteStream(to) + const tmp = join(tmpdir(), rand(64)) + const stream = createWriteStream(tmp) const writer = file.pipe(stream) writer.on('close', () => { stream.close() + try { + // Delete file if already exists. Needed if the binary wants to replace itself. + // Unix does not allow to overwrite a file that is being executed, but you can remove it and save other one at its place + unlinkSync(to) + } catch { + } + renameSync(tmp, to) res() }) })