mirror of
https://github.com/cupcakearmy/autorestic.git
synced 2025-09-06 10:30:39 +00:00
Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
190eca6f6e | |||
805bed7db1 | |||
6c59aa25db | |||
ff648f0017 | |||
c79b45308b | |||
43eabdb204 | |||
0ead9e0da1 | |||
d49e0d3836 | |||
2008ba2771 | |||
1f6c13a595 | |||
8e9b9dcebf | |||
fde4edc05f | |||
7e6cc7bb32 | |||
878a7bd752 | |||
f6860115a3 | |||
f43e73ce41 | |||
6b4277b57b |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.afdesign filter=lfs diff=lfs merge=lfs -text
|
21
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
21
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
<!-- A clear and concise description of what the bug is. -->
|
||||
|
||||
**Expected behavior**
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
**Environment**
|
||||
- OS: [e.g. iOS]
|
||||
- Version: [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
<!-- Add any other context about the problem here. -->
|
4
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
4
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
contact_links:
|
||||
- name: Questions & Help
|
||||
url: https://github.com/cupcakearmy/autorestic/discussions
|
||||
about: Please ask and answer questions here.
|
14
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
14
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
|
||||
|
||||
**Describe the solution you'd like**
|
||||
<!-- A clear and concise description of what you want to happen. -->
|
BIN
.github/logo.afdesign
(Stored with Git LFS)
vendored
Normal file
BIN
.github/logo.afdesign
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,6 +13,7 @@ restore
|
||||
docker
|
||||
Dockerfile
|
||||
build
|
||||
dist
|
||||
|
||||
# Config
|
||||
.autorestic.yml
|
||||
|
@@ -1,3 +1,3 @@
|
||||
## 0.22
|
||||
## 0.27
|
||||
|
||||
- New CI Flag for clean ci output
|
||||
- fix locking issue
|
||||
|
@@ -19,3 +19,7 @@
|
||||
### Why / What?
|
||||
|
||||
Autorestic is a wrapper around the amazing [restic](https://restic.net/). While being amazing the restic cli can be a bit overwhelming and difficult to manage if you have many different location that you want to backup to multiple locations. This utility is aimed at making this easier 🙂
|
||||
|
||||
### Questions / Support
|
||||
|
||||
Check the [discussions page](https://github.com/cupcakearmy/autorestic/discussions)
|
||||
|
@@ -19,4 +19,4 @@ curl -s https://api.github.com/repos/cupcakearmy/autorestic/releases/latest \
|
||||
chmod +x ${OUT_FILE}
|
||||
|
||||
autorestic install
|
||||
autorestic
|
||||
autorestic --help
|
||||
|
@@ -4,7 +4,7 @@
|
||||
"build": "tsc",
|
||||
"dev": "tsc -w",
|
||||
"move": "mv bin/index-linux bin/autorestic_linux_x64 && mv bin/index-macos bin/autorestic_macos_x64",
|
||||
"bin": "yarn run build && pkg lib/index.js --targets latest-macos-x64,latest-linux-x64 --out-path bin && yarn run move",
|
||||
"bin": "yarn run build && pkg dist/index.js --targets latest-macos-x64,latest-linux-x64 --out-path bin && yarn run move",
|
||||
"docs:build": "codedoc install && codedoc build",
|
||||
"docs:dev": "codedoc serve"
|
||||
},
|
||||
@@ -17,12 +17,14 @@
|
||||
"typescript": "^3.9"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/semver": "^7.3.4",
|
||||
"axios": "^0.19",
|
||||
"clitastic": "^0.1.2",
|
||||
"colors": "^1",
|
||||
"commander": "^6.2",
|
||||
"cron-parser": "2.x.x",
|
||||
"js-yaml": "3.x.x",
|
||||
"semver": "^7.3.5",
|
||||
"uhrwerk": "1.x.x"
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { Writer } from 'clitastic'
|
||||
import { mkdirSync } from 'fs'
|
||||
|
||||
import { config, VERBOSE } from './'
|
||||
import { config, hasError, VERBOSE } from './'
|
||||
import { getEnvFromBackend } from './backend'
|
||||
import { LocationFromPrefixes } from './config'
|
||||
import { Locations, Location, Backend } from './types'
|
||||
@@ -68,6 +68,7 @@ export const backupSingle = (name: string, to: string, location: Location) => {
|
||||
|
||||
writer.done(`${name}${to.blue} : ${'Done ✓'.green} (${delta.finished(true)})`)
|
||||
} catch (e) {
|
||||
hasError()
|
||||
writer.done(`${name}${to.blue} : ${'Failed!'.red} (${delta.finished(true)}) ${e.message}`)
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ import { chmodSync } from 'fs'
|
||||
|
||||
import axios from 'axios'
|
||||
import { Writer } from 'clitastic'
|
||||
import semver from 'semver'
|
||||
|
||||
import { INSTALL_DIR, VERSION } from '..'
|
||||
import { checkIfResticIsAvailable, downloadFile, exec } from '../utils'
|
||||
@@ -18,19 +19,25 @@ export async function upgrade() {
|
||||
responseType: 'json',
|
||||
})
|
||||
|
||||
if (json.tag_name != VERSION) {
|
||||
const platformMap: { [key: string]: string } = {
|
||||
darwin: 'macos',
|
||||
const latest = semver.coerce(json.tag_name)
|
||||
const current = semver.coerce(VERSION)
|
||||
if (!latest || !current) throw new Error('Could not parse versions numbers.')
|
||||
if (semver.gt(latest, current) && semver.major(latest) === semver.major(current)) {
|
||||
// Update to compatible
|
||||
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)
|
||||
|
||||
chmodSync(to, 0o755)
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
chmodSync(to, 0o755)
|
||||
}
|
||||
|
||||
w.done('All up to date! 🚀')
|
||||
|
55
src/index.ts
55
src/index.ts
@@ -1,8 +1,8 @@
|
||||
import 'colors'
|
||||
import colors from 'colors'
|
||||
import { program } from 'commander'
|
||||
import { setCIMode } from 'clitastic'
|
||||
|
||||
import { unlock, readLock, writeLock } from './lock'
|
||||
import { unlock, readLock, writeLock, lock } from './lock'
|
||||
import { Config } from './types'
|
||||
import { init } from './config'
|
||||
|
||||
@@ -17,9 +17,15 @@ import install from './handlers/install'
|
||||
import { uninstall } from './handlers/uninstall'
|
||||
import { upgrade } from './handlers/upgrade'
|
||||
|
||||
export const VERSION = '0.23'
|
||||
export const VERSION = '0.28'
|
||||
export const INSTALL_DIR = '/usr/local/bin'
|
||||
|
||||
let requireConfig: boolean = true
|
||||
let error: boolean = false
|
||||
|
||||
export function hasError() {
|
||||
error = true
|
||||
}
|
||||
|
||||
process.on('uncaughtException', (err) => {
|
||||
console.log(err.message)
|
||||
@@ -27,9 +33,9 @@ process.on('uncaughtException', (err) => {
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
let queue: Function = () => {}
|
||||
let queue: () => Promise<void> = async () => {}
|
||||
const enqueue = (fn: Function) => (cmd: any) => {
|
||||
queue = () => fn(cmd.opts())
|
||||
queue = async () => fn(cmd.opts())
|
||||
}
|
||||
|
||||
program.storeOptionsAsProperties()
|
||||
@@ -54,7 +60,7 @@ program
|
||||
.option('-a, --all')
|
||||
.action(enqueue(check))
|
||||
|
||||
program.command('backup').description('Performs a backup').option('-b, --backend <backends...>').option('-a, --all').action(enqueue(backup))
|
||||
program.command('backup').description('Performs a backup').option('-l, --location <locations...>').option('-a, --all').action(enqueue(backup))
|
||||
|
||||
program
|
||||
.command('restore')
|
||||
@@ -84,7 +90,7 @@ program
|
||||
.option('-b, --backend <backends...>')
|
||||
.option('-a, --all')
|
||||
.action(({ args, all, backend }) => {
|
||||
queue = () => exec({ all, backend }, args)
|
||||
queue = async () => exec({ all, backend }, args)
|
||||
})
|
||||
|
||||
program.command('install').description('Installs both restic and autorestic to /usr/local/bin').action(enqueue(install))
|
||||
@@ -105,20 +111,25 @@ const { verbose, config: configFile, ci } = program.parse(process.argv)
|
||||
export const VERBOSE = verbose
|
||||
export let config: Config
|
||||
setCIMode(ci)
|
||||
if (ci) colors.disable()
|
||||
|
||||
try {
|
||||
const lock = readLock()
|
||||
if (lock.running) throw new Error('An instance of autorestic is already running for this config file'.red)
|
||||
|
||||
writeLock({
|
||||
...lock,
|
||||
running: true,
|
||||
})
|
||||
|
||||
if (requireConfig) config = init(configFile)
|
||||
queue()
|
||||
} catch (e) {
|
||||
console.error(e.message)
|
||||
} finally {
|
||||
unlock()
|
||||
async function main() {
|
||||
try {
|
||||
if (requireConfig) {
|
||||
config = init(configFile)
|
||||
const { running } = readLock()
|
||||
if (running) {
|
||||
console.log('An instance of autorestic is already running for this config file'.red)
|
||||
process.exit(1)
|
||||
}
|
||||
lock()
|
||||
}
|
||||
await queue()
|
||||
} catch (e) {
|
||||
console.error(e.message)
|
||||
} finally {
|
||||
if (requireConfig) unlock()
|
||||
}
|
||||
if (error) process.exit(1)
|
||||
}
|
||||
main()
|
||||
|
@@ -30,3 +30,10 @@ export const unlock = () => {
|
||||
running: false,
|
||||
})
|
||||
}
|
||||
|
||||
export const lock = () => {
|
||||
writeLock({
|
||||
...readLock(),
|
||||
running: true,
|
||||
})
|
||||
}
|
||||
|
@@ -1,10 +1,13 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"target": "es2019",
|
||||
"module": "commonjs",
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
"strict": true,
|
||||
"esModuleInterop": true
|
||||
}
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"alwaysStrict": true,
|
||||
"strictNullChecks": true
|
||||
},
|
||||
"include": ["./src"]
|
||||
}
|
||||
|
36
yarn.lock
36
yarn.lock
@@ -3,9 +3,9 @@
|
||||
|
||||
|
||||
"@babel/parser@^7.9.4":
|
||||
version "7.12.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.5.tgz#b4af32ddd473c0bfa643bd7ff0728b8e71b81ea0"
|
||||
integrity sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ==
|
||||
version "7.12.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.7.tgz#fee7b39fe809d0e73e5b25eecaf5780ef3d73056"
|
||||
integrity sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg==
|
||||
|
||||
"@babel/runtime@^7.9.2":
|
||||
version "7.12.5"
|
||||
@@ -52,9 +52,9 @@
|
||||
integrity sha512-JCcp6J0GV66Y4ZMDAQCXot4xprYB+Zfd3meK9+INSJeVZwJmHAW30BBEEkPzXswMXuiyReUGOP3GxrADc9wPww==
|
||||
|
||||
"@types/node@^14":
|
||||
version "14.14.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.7.tgz#8ea1e8f8eae2430cf440564b98c6dfce1ec5945d"
|
||||
integrity sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==
|
||||
version "14.14.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.10.tgz#5958a82e41863cfc71f2307b3748e3491ba03785"
|
||||
integrity sha512-J32dgx2hw8vXrSbu4ZlVhn1Nm3GbeCFNw2FWL8S5QKucHGY0cyNwjdQdO+KMBZ4wpmC7KhLCiNsdk1RFRIYUQQ==
|
||||
|
||||
"@types/strip-bom@^3.0.0":
|
||||
version "3.0.0"
|
||||
@@ -283,9 +283,9 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
||||
cron-parser@2.x.x:
|
||||
version "2.17.0"
|
||||
resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.17.0.tgz#5707421a7e0a73ee74675d1c032a2f14123f2cf8"
|
||||
integrity sha512-oTmzVEwlurRe51HqTm4afshVr8Rkxy9kFiWxh5e6SmrY2o9NDYU4S6SduanBZYXLgkLy0skA98y7/tztW/DmjQ==
|
||||
version "2.18.0"
|
||||
resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.18.0.tgz#de1bb0ad528c815548371993f81a54e5a089edcf"
|
||||
integrity sha512-s4odpheTyydAbTBQepsqd2rNWGa2iV3cyo8g7zbI2QQYGLVsfbhmwukayS1XHppe02Oy1fg7mg6xoaraVJeEcg==
|
||||
dependencies:
|
||||
is-nan "^1.3.0"
|
||||
moment-timezone "^0.5.31"
|
||||
@@ -662,9 +662,9 @@ is-binary-path@~2.1.0:
|
||||
binary-extensions "^2.0.0"
|
||||
|
||||
is-core-module@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz#a4cc031d9b1aca63eecbd18a650e13cb4eeab946"
|
||||
integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a"
|
||||
integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==
|
||||
dependencies:
|
||||
has "^1.0.3"
|
||||
|
||||
@@ -865,9 +865,9 @@ mkdirp@^1.0.4:
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
|
||||
moment-timezone@^0.5.31:
|
||||
version "0.5.31"
|
||||
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.31.tgz#9c40d8c5026f0c7ab46eda3d63e49c155148de05"
|
||||
integrity sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==
|
||||
version "0.5.32"
|
||||
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.32.tgz#db7677cc3cc680fd30303ebd90b0da1ca0dfecc2"
|
||||
integrity sha512-Z8QNyuQHQAmWucp8Knmgei8YNo28aLjJq6Ma+jy1ZSpSk5nyfRT8xgUbSQvD2+2UajISfenndwvFuH3NGS+nvA==
|
||||
dependencies:
|
||||
moment ">= 2.9.0"
|
||||
|
||||
@@ -1280,9 +1280,9 @@ spdx-expression-parse@^3.0.0:
|
||||
spdx-license-ids "^3.0.0"
|
||||
|
||||
spdx-license-ids@^3.0.0:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz#c80757383c28abf7296744998cbc106ae8b854ce"
|
||||
integrity sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65"
|
||||
integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==
|
||||
|
||||
sprintf-js@~1.0.2:
|
||||
version "1.0.3"
|
||||
|
Reference in New Issue
Block a user