Compare commits

...

9 Commits
0.1 ... 0.2

Author SHA1 Message Date
cupcakearmy
edddcebcea Merge remote-tracking branch 'origin/master' 2019-06-21 12:28:11 +02:00
cupcakearmy
793ab1c6fe automagically install restic too 2019-06-21 12:27:59 +02:00
cupcakearmy
9832eeab22 helper for downloading files to disk 2019-06-21 12:27:52 +02:00
cupcakearmy
b1f2678dc1 auto update function 2019-06-21 12:27:39 +02:00
Nicco
64f2eaf16b Update README.md 2019-06-21 12:26:32 +02:00
Nicco
b1b12f4592 Update README.md 2019-06-21 12:25:54 +02:00
cupcakearmy
24a364ce08 install shell script 2019-06-21 12:22:39 +02:00
cupcakearmy
d59362e82c install script 2019-06-20 23:54:23 +02:00
cupcakearmy
0802dedb47 move default config file 2019-06-20 23:54:18 +02:00
5 changed files with 108 additions and 39 deletions

View File

@@ -1,2 +1,9 @@
# autorestic
High level CLI utility for restic
## Installation
```
curl -s https://raw.githubusercontent.com/CupCakeArmy/autorestic/master/install.sh | sh
```

22
install.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/bin/sh
OUT_FILE=/usr/local/bin/autorestic
if [[ "$OSTYPE" == "linux-gnu" ]]; then
TYPE=linux
elif [[ "$OSTYPE" == "darwin"* ]]; then
TYPE=macos
else
echo "Unsupported OS"
exit
fi
curl -s https://api.github.com/repos/cupcakearmy/autorestic/releases/latest \
| grep "browser_download_url.*_${TYPE}" \
| cut -d : -f 2,3 \
| tr -d \" \
| wget -O ${OUT_FILE} -i -
chmod +x ${OUT_FILE}
autorestic install
autorestic

View File

@@ -1,5 +1,6 @@
import 'colors'
import minimist from 'minimist'
import { homedir } from 'os'
import { resolve } from 'path'
import { init } from './config'
@@ -25,9 +26,10 @@ export const { _: commands, ...flags } = minimist(process.argv.slice(2), {
string: ['l', 'b'],
})
export const DEFAULT_CONFIG = 'config.yml'
export const VERSION = '0.1'
export const DEFAULT_CONFIG = '/.autorestic.yml'
export const INSTALL_DIR = '/usr/local/bin'
export const CONFIG_FILE: string = resolve(flags.config || DEFAULT_CONFIG)
export const CONFIG_FILE: string = resolve(flags.config || homedir() + DEFAULT_CONFIG)
export const VERBOSE = flags.verbose
export const config: Config = init()

View File

@@ -1,14 +1,21 @@
import axios from 'axios'
import { Writer } from 'clitastic'
import { createWriteStream, unlinkSync } from 'fs'
import { arch, platform, tmpdir } from 'os'
import { unlinkSync } from 'fs'
import { tmpdir } from 'os'
import { join, resolve } from 'path'
import { config, INSTALL_DIR } from './autorestic'
import { config, CONFIG_FILE, INSTALL_DIR, VERSION } from './autorestic'
import { checkAndConfigureBackends, getEnvFromBackend } from './backend'
import { backupAll } from './backup'
import { Backends, Flags, Locations } from './types'
import { checkIfCommandIsAvailable, checkIfResticIsAvailable, exec, filterObjectByKey, singleToArray } from './utils'
import {
checkIfCommandIsAvailable,
checkIfResticIsAvailable,
downloadFile,
exec,
filterObjectByKey,
singleToArray,
} from './utils'
export type Handlers = { [command: string]: (args: string[], flags: Flags) => void }
@@ -114,63 +121,76 @@ const handlers: Handlers = {
}
w.replaceLn('Downloading binary... 🌎')
const name = `${json.name.replace(' ', '_')}_${platform()}_${archMap[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(
'Cannot get the right binary.'.red,
'Please see https://bit.ly/2Y1Rzai',
)
const { data: file } = await axios({
method: 'get',
url: dl.browser_download_url,
responseType: 'stream',
})
const tmp = join(tmpdir(), name)
const extracted = tmp.slice(0, -4) //without the .bz2
const from = join(tmpdir(), name)
const to = from.slice(0, -4)
await downloadFile(dl.browser_download_url, tmp)
w.replaceLn('Decompressing binary... 📦')
const stream = createWriteStream(from)
await new Promise(res => {
const writer = file.pipe(stream)
writer.on('close', res)
})
stream.close()
w.replaceLn(`Moving to ${INSTALL_DIR} 🚙`)
// TODO: Native bz2
// Decompress
exec('bzip2', ['-dk', from])
// Remove .bz2
exec('chmod', ['+x', to])
exec('mv', [to, INSTALL_DIR + '/restic'])
w.replaceLn('Decompressing binary... 📦')
exec('bzip2', ['-dk', tmp])
unlinkSync(tmp)
unlinkSync(from)
w.replaceLn(`Moving to ${INSTALL_DIR} 🚙`)
exec('chmod', ['+x', extracted])
exec('mv', [extracted, INSTALL_DIR + '/restic'])
w.done(`\nFinished! restic is installed under: ${INSTALL_DIR}`.underline + ' 🎉')
},
uninstall() {
try {
unlinkSync(INSTALL_DIR + '/restic')
console.log(`Finished! restic was uninstalled`)
} catch (e) {
console.log('restic is already uninstalled'.red)
}
for (const bin of ['restic', 'autorestic'])
try {
unlinkSync(INSTALL_DIR + '/' + bin)
console.log(`Finished! ${bin} was uninstalled`)
} catch (e) {
console.log(`${bin} is already uninstalled`.red)
}
},
update() {
async update() {
checkIfResticIsAvailable()
const w = new Writer('Checking for new restic version... ⏳')
const w = new Writer('Checking for latest restic version... ⏳')
exec('restic', ['self-update'])
w.replaceLn('Checking for latest autorestic version... ⏳')
const { data: json } = await axios({
method: 'get',
url: 'https://api.github.com/repos/cupcakearmy/autorestic/releases/latest',
responseType: 'json',
})
if (json.tag_name != VERSION) {
const platformMap: { [key: string]: string } = {
'darwin': 'macos',
}
const name = `autorestic_${platformMap[process.platform] || process.platform}_${process.arch}`
const dl = json.assets.find((asset: any) => asset.name === name)
const to = INSTALL_DIR + '/autorestic'
w.replaceLn('Downloading binary... 🌎')
await downloadFile(dl.browser_download_url, to)
exec('chmod', ['+x', to])
}
w.done('All up to date! 🚀')
},
}
export const help = () => {
console.log('\nAutorestic'.blue + ' - Easy Restic CLI Utility'
console.log('\nAutorestic'.blue + ` - ${VERSION} - Easy Restic CLI Utility`
+ '\n'
+ '\nOptions:'.yellow
+ '\n -c, --config [default=config.yml] Specify config file'
+ `\n -c, --config Specify config file. Default: ${CONFIG_FILE}`
+ '\n'
+ '\nCommands:'.yellow
+ '\n check [-b, --backend] [-a, --all] Check backends'

View File

@@ -1,5 +1,7 @@
import axios from 'axios'
import { spawnSync, SpawnSyncOptions } from 'child_process'
import { randomBytes } from 'crypto'
import { createWriteStream } from 'fs'
export const exec = (command: string, args: string[], { env, ...rest }: SpawnSyncOptions = {}) => {
@@ -43,3 +45,19 @@ export const singleToArray = <T>(singleOrArray: T | T[]): T[] => Array.isArray(s
export const filterObject = <T>(obj: { [key: string]: T }, filter: (item: [string, T]) => boolean): { [key: string]: T } => Object.fromEntries(Object.entries(obj).filter(filter))
export const filterObjectByKey = <T>(obj: { [key: string]: T }, keys: string[]) => filterObject(obj, ([key]) => keys.includes(key))
export const downloadFile = async (url: string, to: string) => new Promise<void>(async res => {
const { data: file } = await axios({
method: 'get',
url: url,
responseType: 'stream',
})
const stream = createWriteStream(to)
const writer = file.pipe(stream)
writer.on('close', () => {
stream.close()
res()
})
})