mirror of
https://github.com/cupcakearmy/autorestic.git
synced 2025-09-06 10:30:39 +00:00
Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
5c0b67b7fb | |||
1520e10a59 | |||
f9c645120b |
@@ -4,11 +4,11 @@ import minimist from 'minimist'
|
||||
import { init } from './config'
|
||||
import handlers, { error, help } from './handlers'
|
||||
import { Config } from './types'
|
||||
|
||||
|
||||
import { readLock, writeLock, unlock } from './lock'
|
||||
|
||||
process.on('uncaughtException', err => {
|
||||
console.log(err.message)
|
||||
unlock()
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
@@ -26,7 +26,7 @@ export const { _: commands, ...flags } = minimist(process.argv.slice(2), {
|
||||
string: ['l', 'b'],
|
||||
})
|
||||
|
||||
export const VERSION = '0.17'
|
||||
export const VERSION = '0.18'
|
||||
export const INSTALL_DIR = '/usr/local/bin'
|
||||
export const VERBOSE = flags.verbose
|
||||
|
||||
@@ -36,6 +36,17 @@ export let config: Config
|
||||
async function main() {
|
||||
config = init()
|
||||
|
||||
// Don't let 2 instances run on the same config
|
||||
const lock = readLock()
|
||||
if (lock.running) {
|
||||
console.log('An instance of autorestic is already running for this config file'.red)
|
||||
return
|
||||
}
|
||||
writeLock({
|
||||
...lock,
|
||||
running: true,
|
||||
})
|
||||
|
||||
// For dev
|
||||
// return await handlers['cron']([], { ...flags, all: true })
|
||||
|
||||
@@ -46,6 +57,7 @@ async function main() {
|
||||
|
||||
const fn = handlers[command] || error
|
||||
await fn(args, flags)
|
||||
unlock()
|
||||
}
|
||||
|
||||
|
||||
|
40
src/cron.ts
40
src/cron.ts
@@ -1,49 +1,21 @@
|
||||
import fs from 'fs'
|
||||
|
||||
import CronParser from 'cron-parser'
|
||||
|
||||
import { config } from './autorestic'
|
||||
import { checkAndConfigureBackendsForLocations } from './backend'
|
||||
import { Location, Lockfile } from './types'
|
||||
import { Location } from './types'
|
||||
import { backupLocation } from './backup'
|
||||
import { pathRelativeToConfigFile } from './utils'
|
||||
import { readLock, writeLock } from './lock'
|
||||
|
||||
|
||||
const getLockFileName = () => {
|
||||
const LOCK_FILE = '.autorestic.lock'
|
||||
return pathRelativeToConfigFile(LOCK_FILE)
|
||||
}
|
||||
|
||||
const readLock = (): Lockfile => {
|
||||
const name = getLockFileName()
|
||||
let lock = {}
|
||||
try {
|
||||
lock = JSON.parse(fs.readFileSync(name, { encoding: 'utf-8' }))
|
||||
} catch { }
|
||||
return lock
|
||||
}
|
||||
const writeLock = (diff: Lockfile = {}) => {
|
||||
const name = getLockFileName()
|
||||
const newLock = Object.assign(
|
||||
readLock(),
|
||||
diff
|
||||
)
|
||||
fs.writeFileSync(name, JSON.stringify(newLock, null, 2), { encoding: 'utf-8' })
|
||||
}
|
||||
|
||||
const runCronForLocation = (name: string, location: Location) => {
|
||||
const lock = readLock()[name]
|
||||
const lock = readLock()
|
||||
const parsed = CronParser.parseExpression(location.cron || '')
|
||||
const last = parsed.prev()
|
||||
|
||||
if (!lock || last.toDate().getTime() > lock.lastRun) {
|
||||
if (!lock.crons[name] || last.toDate().getTime() > lock.crons[name].lastRun) {
|
||||
backupLocation(name, location)
|
||||
writeLock({
|
||||
[name]: {
|
||||
...lock,
|
||||
lastRun: Date.now()
|
||||
}
|
||||
})
|
||||
lock.crons[name] = { lastRun: Date.now() }
|
||||
writeLock(lock)
|
||||
} else {
|
||||
console.log(`${name.yellow} ▶ Skipping. Sheduled for: ${parsed.next().toString().underline.blue}`)
|
||||
}
|
||||
|
32
src/lock.ts
Normal file
32
src/lock.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import fs from 'fs'
|
||||
|
||||
import { pathRelativeToConfigFile } from "./utils"
|
||||
import { Lockfile } from "./types"
|
||||
|
||||
export const getLockFileName = () => {
|
||||
const LOCK_FILE = '.autorestic.lock'
|
||||
return pathRelativeToConfigFile(LOCK_FILE)
|
||||
}
|
||||
|
||||
export const readLock = (): Lockfile => {
|
||||
const name = getLockFileName()
|
||||
let lock = {
|
||||
running: false,
|
||||
crons: {}
|
||||
}
|
||||
try {
|
||||
lock = JSON.parse(fs.readFileSync(name, { encoding: 'utf-8' }))
|
||||
} catch { }
|
||||
return lock
|
||||
}
|
||||
export const writeLock = (lock: Lockfile) => {
|
||||
const name = getLockFileName()
|
||||
fs.writeFileSync(name, JSON.stringify(lock, null, 2), { encoding: 'utf-8' })
|
||||
}
|
||||
|
||||
export const unlock = () => {
|
||||
writeLock({
|
||||
...readLock(),
|
||||
running: false,
|
||||
})
|
||||
}
|
@@ -93,9 +93,12 @@ export type Config = {
|
||||
}
|
||||
|
||||
export type Lockfile = {
|
||||
running: boolean
|
||||
crons: {
|
||||
[name: string]: {
|
||||
lastRun: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type Flags = { [arg: string]: any }
|
||||
|
@@ -30,7 +30,7 @@ export const execPlain = (command: string, opt: SpawnSyncOptions = {}) => {
|
||||
const split = command.split(' ')
|
||||
if (split.length < 1) throw new Error(`The command ${command} is not valid`.red)
|
||||
|
||||
return exec(split[0], split.slice(1), opt)
|
||||
return exec(split[0], split.slice(1), { shell: true, ...opt })
|
||||
}
|
||||
|
||||
export const checkIfResticIsAvailable = () =>
|
||||
@@ -42,7 +42,7 @@ export const checkIfResticIsAvailable = () =>
|
||||
)
|
||||
|
||||
export const checkIfCommandIsAvailable = (cmd: string, errorMsg?: string) => {
|
||||
if (spawnSync(cmd).error)
|
||||
if (spawnSync(cmd, { shell: true }).error)
|
||||
throw new Error(errorMsg ? errorMsg : `"${cmd}" is not installed`.red)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user