Compare commits

...

33 Commits

Author SHA1 Message Date
Nicco 62a81d1420
add blog post to community page :) 2024-05-17 19:23:54 +02:00
Nicco e4b33cad1f
version bump 2024-03-28 09:29:39 +01:00
Tucker Kern a82273ec13
Allow REST backend with docker volumes (#366) 2024-03-27 20:20:13 +01:00
dependabot[bot] 2418da5636
Bump gopkg.in/yaml.v3 from 3.0.0-20210107192922-496545a6307b to 3.0.0 (#363)
Bumps gopkg.in/yaml.v3 from 3.0.0-20210107192922-496545a6307b to 3.0.0.

---
updated-dependencies:
- dependency-name: gopkg.in/yaml.v3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-25 22:47:08 +01:00
dependabot[bot] 7508df7d66
Bump katex from 0.16.8 to 0.16.10 in /docs (#364)
Bumps [katex](https://github.com/KaTeX/KaTeX) from 0.16.8 to 0.16.10.
- [Release notes](https://github.com/KaTeX/KaTeX/releases)
- [Changelog](https://github.com/KaTeX/KaTeX/blob/main/CHANGELOG.md)
- [Commits](https://github.com/KaTeX/KaTeX/compare/v0.16.8...v0.16.10)

---
updated-dependencies:
- dependency-name: katex
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-25 22:46:58 +01:00
Nicco 6e34196220
Update config.go 2024-03-13 12:40:11 +01:00
Florian dc56911a45
fix(unlock cmd): ignore process if its the current id (#360) 2024-03-13 12:39:51 +01:00
Nicco edb3ba35d8
Update config.go 2024-03-12 15:27:11 +01:00
Florian 12f6143bb4
fix: cli command to unlock the autorestic running value (#329)
* fix: cli command to unlock the autorestic running value

* fix(unlock cmd): get user confirmation in case an instance is still running

* fix(cmd unlock): add force flag
2024-03-12 15:26:12 +01:00
Pete a6bf1d1408
fix relative path to options forget (#331)
/location/options/forget instead of /location/forget.
2024-03-12 15:24:25 +01:00
Stuart Hickinbottom 13aa560fda
Add PreValidate hook (#359)
Fix #332.

This adds a new "PreValidate" hook that is executed before checking
the backup location. This allows, for example, mounting a remote
source to make the directories of the location available.

"PreValidate" is added as a new hook to avoid any breakage that might
have been caused by changing the behaviour of the "before" hook.

Documentataion updates included.
2024-03-12 15:22:43 +01:00
Romain de Laage bbb1c85cad
Fix upgrade command (#259)
fix #191

Co-authored-by: Romain de Laage <romain.delaage@rdelaage.ovh>
2024-02-15 14:27:37 +01:00
Natanel Shitrit 4cc44315ab
feat: add `docker-cli` package (#339)
Co-authored-by: Nicco <hi@nicco.io>
2024-02-15 14:26:26 +01:00
dependabot[bot] b3440cd87c
Bump golang from 1.21-alpine to 1.22-alpine (#355)
Bumps golang from 1.21-alpine to 1.22-alpine.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-15 14:24:17 +01:00
Romain de Laage 4848702929
Use options on exec command (#253)
Co-authored-by: Romain de Laage <romain.delaage@rdelaage.ovh>
2024-02-15 14:23:43 +01:00
Nicco b5604b8b9f
update deps (#353) 2024-02-09 14:18:24 +01:00
Alexander Zhang 24220f6b62
Fix broken link in docs (#350) 2024-02-09 14:18:06 +01:00
Niccolo Borgioli ced20801c1
bump version 2024-01-11 19:17:53 +01:00
Christoph Loy ce9140fa1e
Fix handling of `XDG_CONFIG_HOME` (#347) 2024-01-11 19:01:59 +01:00
Matthias Liffers 046c79fd15
Add curl to docker image (#344) 2024-01-11 18:56:35 +01:00
Skye J f8603425d1
Update installation.md to add AUR back (#348)
I have been maintaining the AUR package, so it is no longer deprecated.
2024-01-11 18:52:23 +01:00
Niccolo Borgioli 068121d722
adjust base url 2023-10-11 21:50:43 +02:00
Nicco 8eea7d33f8
delete old docs (#327)
* delete old docs

* new docs
2023-10-08 19:24:04 +02:00
Vladimir Mikryukov fc8b5fdbe2
fix typos in `cron.md` (#316) 2023-10-02 14:10:51 +02:00
Christoph Loy f67bb7f73c
Bump version to 1.7.9 (#325) 2023-10-02 14:09:34 +02:00
Christoph Loy 530b1b646c
Update restic to 0.16.0 (#324) 2023-10-02 11:08:28 +02:00
Major Hayden 3b57602fe8
Docs: Add Fedora installation choice (#320)
Fedora now has an autorestic package and users can install it directly
from Fedora's repositories.

Signed-off-by: Major Hayden <major@mhtx.net>
2023-08-01 13:10:12 +02:00
Mikel Olasagasti Uranga 045513234f
Use Printf instead of Println (#318)
Testing in Fedora reports:

./root.go:58:4: (*github.com/fatih/color.Color).Println call has
possible Printf formatting directive %s
2023-07-31 10:03:18 +02:00
dependabot[bot] 78b0db50e0
Bump webpack from 5.75.0 to 5.76.1 in /docs/.codedoc (#295)
Bumps [webpack](https://github.com/webpack/webpack) from 5.75.0 to 5.76.1.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.75.0...v5.76.1)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-22 15:25:32 +01:00
dependabot[bot] 62dd371d51
Bump webpack from 5.75.0 to 5.76.1 in /docs (#296)
Bumps [webpack](https://github.com/webpack/webpack) from 5.75.0 to 5.76.1.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.75.0...v5.76.1)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-22 15:25:20 +01:00
dependabot[bot] 08766b75db
Bump prismjs from 1.23.0 to 1.29.0 in /docs/.codedoc (#269)
Bumps [prismjs](https://github.com/PrismJS/prism) from 1.23.0 to 1.29.0.
- [Release notes](https://github.com/PrismJS/prism/releases)
- [Changelog](https://github.com/PrismJS/prism/blob/master/CHANGELOG.md)
- [Commits](https://github.com/PrismJS/prism/compare/v1.23.0...v1.29.0)

---
updated-dependencies:
- dependency-name: prismjs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-22 15:25:05 +01:00
cupcakearmy b3b7c8df95
update versions 2023-03-05 17:52:40 +01:00
cupcakearmy 2c5266c9a0
fix build system 2023-03-05 17:22:03 +01:00
78 changed files with 3438 additions and 8106 deletions

View File

@ -3,19 +3,19 @@ name: Main
on: on:
push: push:
tags: tags:
- "v*.*.*" - 'v*.*.*'
jobs: jobs:
docker: docker:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v1 uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v2
- name: Docker Labels - name: Docker Labels
id: meta id: meta
uses: crazy-max/ghaction-docker-meta@v2 uses: crazy-max/ghaction-docker-meta@v4
with: with:
images: cupcakearmy/autorestic images: cupcakearmy/autorestic
tags: | tags: |
@ -23,12 +23,12 @@ jobs:
type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}} type=semver,pattern={{major}}
- name: Login to DockerHub - name: Login to DockerHub
uses: docker/login-action@v1 uses: docker/login-action@v2
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push - name: Build and push
uses: docker/build-push-action@v2 uses: docker/build-push-action@v3
with: with:
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
push: true push: true
@ -37,17 +37,12 @@ jobs:
release: release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/setup-go@v2 - uses: actions/setup-go@v3
with: with:
go-version: "^1.16.3" go-version: '^1.21'
- name: Build - name: Build
run: go run build/build.go run: go run build/build.go
- name: Sign
uses: tristan-weil/ghaction-checksum-sign-artifact@v1.0.1
with:
path: dist/*
- name: Release - name: Release
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
with: with:

View File

@ -1,4 +1,4 @@
FROM golang:1.20-alpine as builder FROM golang:1.22-alpine as builder
WORKDIR /app WORKDIR /app
COPY go.* . COPY go.* .
@ -6,8 +6,8 @@ RUN go mod download
COPY . . COPY . .
RUN go build RUN go build
FROM restic/restic:0.15.1 FROM restic/restic:0.16.4
RUN apk add --no-cache rclone bash RUN apk add --no-cache rclone bash curl docker-cli
COPY --from=builder /app/autorestic /usr/bin/autorestic COPY --from=builder /app/autorestic /usr/bin/autorestic
ENTRYPOINT [] ENTRYPOINT []
CMD [ "autorestic" ] CMD [ "autorestic" ]

View File

@ -34,7 +34,7 @@ Autorestic is a wrapper around the amazing [restic](https://restic.net/). While
- Backup locations to multiple backends - Backup locations to multiple backends
- Snapshot policies and pruning - Snapshot policies and pruning
- Fully encrypted - Fully encrypted
- Pre/After hooks - Before/after backup hooks
- Exclude pattern/files - Exclude pattern/files
- Cron jobs for automatic backup - Cron jobs for automatic backup
- Backup & Restore docker volume - Backup & Restore docker volume

View File

@ -4,7 +4,11 @@
package main package main
import ( import (
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path" "path"
@ -31,12 +35,37 @@ type buildOptions struct {
Target, Arch, Version string Target, Arch, Version string
} }
func build(options buildOptions, wg *sync.WaitGroup) { const (
fmt.Printf("Building %s %s\n", options.Target, options.Arch) CHECKSUM_MD5 = "MD5SUMS"
CHECKSUM_SHA_1 = "SHA1SUMS"
CHECKSUM_SHA_256 = "SHA256SUMS"
)
type Checksums struct {
filename, md5, sha1, sha256 string
}
func writeChecksums(checksums *[]Checksums) {
FILE_MD5, _ := os.OpenFile(path.Join(DIR, CHECKSUM_MD5), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
defer FILE_MD5.Close()
FILE_SHA1, _ := os.OpenFile(path.Join(DIR, CHECKSUM_SHA_1), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
defer FILE_SHA1.Close()
FILE_SHA256, _ := os.OpenFile(path.Join(DIR, CHECKSUM_SHA_256), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
defer FILE_SHA256.Close()
for _, checksum := range *checksums {
fmt.Fprintf(FILE_MD5, "%s %s\n", checksum.md5, checksum.filename)
fmt.Fprintf(FILE_SHA1, "%s %s\n", checksum.sha1, checksum.filename)
fmt.Fprintf(FILE_SHA256, "%s %s\n", checksum.sha256, checksum.filename)
}
}
func build(options buildOptions, wg *sync.WaitGroup, checksums *[]Checksums) {
defer wg.Done()
fmt.Printf("Building: %s %s\n", options.Target, options.Arch)
out := fmt.Sprintf("autorestic_%s_%s_%s", options.Version, options.Target, options.Arch) out := fmt.Sprintf("autorestic_%s_%s_%s", options.Version, options.Target, options.Arch)
out = path.Join(DIR, out) out = path.Join(DIR, out)
out, _ = filepath.Abs(out)
fmt.Println(out)
// Build // Build
{ {
@ -65,22 +94,39 @@ func build(options buildOptions, wg *sync.WaitGroup) {
panic(err) panic(err)
} }
} }
wg.Done()
// Checksum
{
file := out + ".bz2"
content, _ := ioutil.ReadFile(file)
*checksums = append(*checksums, Checksums{
filename: path.Base(file),
md5: fmt.Sprintf("%x", md5.Sum(content)),
sha1: fmt.Sprintf("%x", sha1.Sum(content)),
sha256: fmt.Sprintf("%x", sha256.Sum256(content)),
})
}
fmt.Printf("Built: %s\n", path.Base(out))
} }
func main() { func main() {
os.RemoveAll(DIR) os.RemoveAll(DIR)
v := internal.VERSION v := internal.VERSION
checksums := []Checksums{}
// Build async
var wg sync.WaitGroup var wg sync.WaitGroup
for target, archs := range targets { for target, archs := range targets {
for _, arch := range archs { for _, arch := range archs {
wg.Add(1) wg.Add(1)
build(buildOptions{ go build(buildOptions{
Target: target, Target: target,
Arch: arch, Arch: arch,
Version: v, Version: v,
}, &wg) }, &wg, &checksums)
} }
} }
wg.Wait() wg.Wait()
writeChecksums(&checksums)
} }

View File

@ -55,28 +55,11 @@ func initConfig() {
viper.SetConfigFile(cfgFile) viper.SetConfigFile(cfgFile)
viper.AutomaticEnv() viper.AutomaticEnv()
if viper.ConfigFileUsed() == "" { if viper.ConfigFileUsed() == "" {
colors.Error.Println("cannot read config file %s\n", cfgFile) colors.Error.Printf("cannot read config file %s\n", cfgFile)
os.Exit(1) os.Exit(1)
} }
} else { } else {
configPaths := []string{"."} configPaths := getConfigPaths()
// Home
if home, err := homedir.Dir(); err == nil {
configPaths = append(configPaths, home)
}
// XDG_CONFIG_HOME
{
prefix, found := os.LookupEnv("XDG_CONFIG_HOME")
if !found {
if home, err := homedir.Dir(); err != nil {
prefix = filepath.Join(home, ".config")
}
}
xdgConfig := filepath.Join(prefix, "autorestic")
configPaths = append(configPaths, xdgConfig)
}
for _, cfgPath := range configPaths { for _, cfgPath := range configPaths {
viper.AddConfigPath(cfgPath) viper.AddConfigPath(cfgPath)
} }
@ -88,3 +71,22 @@ func initConfig() {
viper.AutomaticEnv() viper.AutomaticEnv()
} }
} }
func getConfigPaths() []string {
result := []string{"."}
if home, err := homedir.Dir(); err == nil {
result = append(result, home)
}
{
xdgConfigHome, found := os.LookupEnv("XDG_CONFIG_HOME")
if !found {
if home, err := homedir.Dir(); err == nil {
xdgConfigHome = filepath.Join(home, ".config")
}
}
xdgConfig := filepath.Join(xdgConfigHome, "autorestic")
result = append(result, xdgConfig)
}
return result
}

36
cmd/root_test.go Normal file
View File

@ -0,0 +1,36 @@
package cmd
import (
"github.com/mitchellh/go-homedir"
"os"
"path/filepath"
"slices"
"testing"
)
const xdgConfigHome = "XDG_CONFIG_HOME"
func assertContains(t *testing.T, array []string, element string) {
if !slices.Contains(array, element) {
t.Errorf("Expected %s to be contained in %s", element, array)
}
}
func TestConfigResolving(t *testing.T) {
t.Run("~/.config/autorestic is used if XDG_CONFIG_HOME is not set", func(t *testing.T) {
// Override env using testing so that env gets restored after test
t.Setenv(xdgConfigHome, "")
_ = os.Unsetenv("XDG_CONFIG_HOME")
configPaths := getConfigPaths()
homeDir, _ := homedir.Dir()
expectedConfigPath := filepath.Join(homeDir, ".config/autorestic")
assertContains(t, configPaths, expectedConfigPath)
})
t.Run("XDG_CONFIG_HOME is respected if set", func(t *testing.T) {
t.Setenv(xdgConfigHome, "/foo/bar")
configPaths := getConfigPaths()
assertContains(t, configPaths, filepath.Join("/", "foo", "bar", "autorestic"))
})
}

81
cmd/unlock.go Normal file
View File

@ -0,0 +1,81 @@
package cmd
import (
"bytes"
"fmt"
"os"
"os/exec"
"strings"
"github.com/cupcakearmy/autorestic/internal"
"github.com/cupcakearmy/autorestic/internal/colors"
"github.com/cupcakearmy/autorestic/internal/lock"
"github.com/spf13/cobra"
)
var unlockCmd = &cobra.Command{
Use: "unlock",
Short: "Unlock autorestic only if you are sure that no other instance is running",
Long: `Unlock autorestic only if you are sure that no other instance is running.
To check you can run "ps aux | grep autorestic".`,
Run: func(cmd *cobra.Command, args []string) {
internal.GetConfig()
force, _ := cmd.Flags().GetBool("force")
if !force && isAutoresticRunning() {
colors.Error.Print("Another autorestic instance is running. Are you sure you want to unlock? (yes/no): ")
var response string
fmt.Scanln(&response)
if strings.ToLower(response) != "yes" {
colors.Primary.Println("Unlocking aborted.")
return
}
}
err := lock.Unlock()
if err != nil {
colors.Error.Println("Could not unlock:", err)
return
}
colors.Success.Println("Unlock successful")
},
}
func init() {
rootCmd.AddCommand(unlockCmd)
unlockCmd.Flags().Bool("force", false, "force unlock")
}
// isAutoresticRunning checks if autorestic is running
// and returns true if it is.
// It also prints the processes to stdout.
func isAutoresticRunning() bool {
cmd := exec.Command("sh", "-c", "ps aux | grep autorestic")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
return false
}
lines := strings.Split(out.String(), "\n")
autoresticProcesses := []string{}
currentPid := fmt.Sprint(os.Getpid())
for _, line := range lines {
if strings.Contains(line, "autorestic") && !strings.Contains(line, "grep autorestic") && !strings.Contains(line, currentPid) {
autoresticProcesses = append(autoresticProcesses, line)
}
}
if len(autoresticProcesses) > 0 {
colors.Faint.Println("Found autorestic processes:")
for _, proc := range autoresticProcesses {
colors.Faint.Println(proc)
}
return true
}
return false
}

View File

@ -1,15 +0,0 @@
import { build } from '@codedoc/core';
import { config } from './config';
import { installTheme$ } from './content/theme';
import { content } from './content';
build(config, content, installTheme$, {
resolve: {
modules: ['.codedoc/node_modules']
},
resolveLoader: {
modules: ['.codedoc/node_modules']
}
});

View File

@ -1,24 +0,0 @@
import { configuration } from '@codedoc/core'
export const config = configuration({
src: {
base: 'markdown',
},
dest: {
html: './build',
assets: './build',
bundle: './_',
styles: './_',
},
page: {
title: {
base: 'Autorestic',
},
},
misc: {
github: {
user: 'cupcakearmy',
repo: 'autorestic',
},
},
})

View File

@ -1,19 +0,0 @@
import { CodedocConfig } from '@codedoc/core';
import { Footer as _Footer, GitterToggle$, Watermark} from '@codedoc/core/components';
export function Footer(config: CodedocConfig, renderer: any) {
let github$;
if (config.misc?.github)
github$ = <a href={`https://github.com/${config.misc.github.user}/${config.misc.github.repo}/`}
target="_blank">GitHub</a>;
let community$;
if (config.misc?.gitter)
community$ = <GitterToggle$ room={config.misc.gitter.room}/>
if (github$ && community$) return <_Footer>{github$}<hr/>{community$}</_Footer>;
else if (github$) return <_Footer>{github$}</_Footer>;
else if (community$) return <_Footer>{community$}</_Footer>;
else return <_Footer><Watermark/></_Footer>;
}

View File

@ -1,21 +0,0 @@
import { CodedocConfig } from '@codedoc/core';
import { Header as _Header, GithubButton, Watermark } from '@codedoc/core/components';
export function Header(config: CodedocConfig, renderer: any) {
return (
<_Header>{config.misc?.github ?
<fragment>
<GithubButton action={config.misc.github.action || 'Star'}
repo={config.misc.github.repo}
user={config.misc.github.user}
large={config.misc.github.large === true}
count={config.misc.github.count !== false}
standardIcon={config.misc.github.standardIcon !== false}/>
<br/><br/>
</fragment>
: ''}
<Watermark/>
</_Header>
)
}

View File

@ -1,57 +0,0 @@
import { RendererLike } from '@connectv/html'
import { File } from 'rxline/fs'
import {
Page,
Meta,
ContentNav,
Fonts,
ToC,
GithubSearch$,
} from '@codedoc/core/components'
import { config } from '../config'
import { Header } from './header'
import { Footer } from './footer'
export function content(
_content: HTMLElement,
toc: HTMLElement,
renderer: RendererLike<any, any>,
file: File<string>
) {
return (
<Page
title={config.page.title.extractor(_content, config, file)}
favicon={config.page.favicon}
meta={<Meta {...config.page.meta} />}
fonts={<Fonts {...config.page.fonts} />}
scripts={config.page.scripts}
stylesheets={config.page.stylesheets}
header={<Header {...config} />}
footer={<Footer {...config} />}
toc={
<ToC
default={'open'}
search={
config.misc?.github ? (
<GithubSearch$
repo={config.misc.github.repo}
user={config.misc.github.user}
root={config.src.base}
pick={config.src.pick.source}
drop={config.src.drop.source}
/>
) : (
false
)
}
>
{toc}
</ToC>
}
>
{_content}
<ContentNav content={_content} />
</Page>
)
}

View File

@ -1,8 +0,0 @@
import { funcTransport } from '@connectv/sdh/transport';
import { useTheme } from '@codedoc/core/transport';
import { theme } from '../theme';
export function installTheme() { useTheme(theme); }
export const installTheme$ = /*#__PURE__*/funcTransport(installTheme);

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +0,0 @@
{
"dependencies": {
"@codedoc/core": "^0.3.2"
}
}

View File

@ -1,18 +0,0 @@
import { join } from 'path';
import { serve } from '@codedoc/core';
import { config } from './config';
import { content } from './content';
import { installTheme$ } from './content/theme';
const root = join(__dirname, '../');
serve(root, config, content, installTheme$, {
resolve: {
modules: ['.codedoc/node_modules']
},
resolveLoader: {
modules: ['.codedoc/node_modules']
}
});

View File

@ -1,11 +0,0 @@
import { createTheme } from '@codedoc/core/transport';
export const theme = /*#__PURE__*/createTheme({
light: {
primary: '#1eb2a6'
},
dark: {
primary: '#1eb2a6'
}
});

View File

@ -1,26 +0,0 @@
{
"compilerOptions": {
"target": "es6",
"noImplicitAny": true,
"declaration": false,
"strictNullChecks": true,
"strictFunctionTypes": true,
"noImplicitThis": true,
"alwaysStrict": true,
"sourceMap": true,
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"jsx": "react",
"jsxFactory": "renderer.create",
"lib": [
"es2017",
"dom"
]
},
"include": [
"./**/*"
]
}

View File

@ -1,22 +0,0 @@
import { exec, spawn } from 'child_process';
import { config } from './config';
const cmd = 'ts-node-dev';
const params = `--project .codedoc/tsconfig.json`
+ ` -T --watch ${config.src.base},.codedoc`
+ ` --ignore-watch .codedoc/node_modules`
+ ` .codedoc/serve`;
if (process.platform === 'win32') {
const child = exec(cmd + ' ' + params);
child.stdout?.pipe(process.stdout);
child.stderr?.pipe(process.stderr);
child.on('close', () => {});
}
else {
const child = spawn(cmd, [params], { stdio: 'inherit', shell: 'bash' });
child.on('close', () => {});
}

2
docs/.gitignore vendored
View File

@ -1,2 +1,2 @@
node_modules node_modules
build .next

1
docs/.nvmrc Normal file
View File

@ -0,0 +1 @@
v20.8.0

View File

@ -1,54 +0,0 @@
[Home](/)
[Quick Start](/quick)
[Installation](/installation)
[Configuration](/config)
[Upgrade](/upgrade)
> :Collapse label=Locations
>
> [Overview](/location/overview)
> [Hooks](/location/hooks)
>
> > :Collapse label=Options
> >
> > [Overview](/location/options)
> > [Excluding Files](/location/exclude)
> > [Forget Policy](/location/forget)
> > [Copy](/location/copy)
>
> [Cron](/location/cron)
> [Docker Volumes](/location/docker)
> :Collapse label=Backend
>
> [Overview](/backend/overview)
> [Available Backends](/backend/available)
> [Options](/backend/options)
> [Environment](/backend/env)
> :Collapse label=CLI
>
> [General](/cli/general)
> [Info](/cli/info)
> [Check](/cli/check)
> [Completion](/cli/completion)
> [Backup](/cli/backup)
> [Restore](/cli/restore)
> [Forget](/cli/forget)
> [Cron](/cli/cron)
> [Exec](/cli/exec)
> [Install](/cli/install)
> [Uninstall](/cli/uninstall)
> [Upgrade](/cli/upgrade)
> :Collapse label=Migration
>
> [0.x → 1.0](/migration/0.x_1.0)
> [1.4 → 1.5](/migration/1.4_1.5)
[Examples](/examples)
[Docker](/docker)
[QA](/qa)
[Community](/community)
[Contributors](/contrib)

6
docs/next.config.js Normal file
View File

@ -0,0 +1,6 @@
const withNextra = require('nextra')({
theme: 'nextra-theme-docs',
themeConfig: './theme.config.jsx',
})
module.exports = withNextra()

2741
docs/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,14 @@
{ {
"private": true,
"scripts": { "scripts": {
"build": "codedoc install && codedoc build", "build": "NEXT_TELEMETRY_DISABLED=1 next build",
"dev": "codedoc serve" "dev": "NEXT_TELEMETRY_DISABLED=1 next"
}, },
"dependencies": { "dependencies": {
"@codedoc/cli": "^0.3.0" "next": "^13.5.3",
} "nextra": "^2.13.1",
"nextra-theme-docs": "^2.13.1",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"packageManager": "pnpm@8.8.0"
} }

10
docs/pages/_meta.json Normal file
View File

@ -0,0 +1,10 @@
{
"index": "Home",
"quick": "Quick Start",
"installation": "Installation",
"config": "Configuration",
"location": "Locations",
"backend": "Backend",
"cli": "CLI",
"migration": "Migration"
}

View File

@ -0,0 +1,6 @@
{
"index": "Overview",
"available": "Available backends",
"options": "Options",
"env": "Environment"
}

View File

@ -83,5 +83,3 @@ backends:
user: user user: user
password: pass password: pass
``` ```
> :ToCPrevNext

View File

@ -63,5 +63,3 @@ backends:
type: b2 type: b2
path: myBucket path: myBucket
``` ```
> :ToCPrevNext

View File

@ -16,5 +16,3 @@ backends:
## Types ## Types
We restic supports multiple types of backends. See the [full list](/backend/available) for details. We restic supports multiple types of backends. See the [full list](/backend/available) for details.
> :ToCPrevNext

View File

@ -15,5 +15,3 @@ backend:
``` ```
In this example, whenever `autorestic` runs `restic backup` it will append a `--tag abc --tag` to the native command. In this example, whenever `autorestic` runs `restic backup` it will append a `--tag abc --tag` to the native command.
> :ToCPrevNext

View File

@ -0,0 +1,3 @@
{
"general": "General"
}

View File

@ -21,5 +21,3 @@ autorestic backup -l foo -l bar
```bash ```bash
autorestic backup -l location@backend autorestic backup -l location@backend
``` ```
> :ToCPrevNext

View File

@ -7,5 +7,3 @@ autorestic check
Checks locations and backends are configured properly and initializes them if they are not already. Checks locations and backends are configured properly and initializes them if they are not already.
This is mostly an internal command, but useful to verify if a backend is configured correctly. This is mostly an internal command, but useful to verify if a backend is configured correctly.
> :ToCPrevNext

View File

@ -13,5 +13,3 @@ Supported shells are
- powershell - powershell
To see how to install run `autorestic help completion` and follow the instructions for your specific shell To see how to install run `autorestic help completion` and follow the instructions for your specific shell
> :ToCPrevNext

View File

@ -9,5 +9,3 @@ This command is mostly intended to be triggered by an automated system like syst
It will run cron jobs as [specified in the cron section](/location/cron) of a specific location. It will run cron jobs as [specified in the cron section](/location/cron) of a specific location.
The `--lean` flag will omit output like _skipping location x: not due yet_. This can be useful if you are dumping the output of the cron job to a log file and don't want to be overwhelmed by the output log. The `--lean` flag will omit output like _skipping location x: not due yet_. This can be useful if you are dumping the output of the cron job to a log file and don't want to be overwhelmed by the output log.
> :ToCPrevNext

View File

@ -11,5 +11,3 @@ autorestic exec -av -- snapshots
``` ```
With `exec` you can basically run every cli command that you would be able to run with the restic cli. It only pre-fills path, key, etc. With `exec` you can basically run every cli command that you would be able to run with the restic cli. It only pre-fills path, key, etc.
> :ToCPrevNext

View File

@ -4,10 +4,8 @@
autorestic forget [-l, --location] [-a, --all] [--dry-run] [--prune] autorestic forget [-l, --location] [-a, --all] [--dry-run] [--prune]
``` ```
This will prune and remove old data form the backends according to the [keep policy you have specified for the location](/location/forget). This will prune and remove old data form the backends according to the [keep policy you have specified for the location](/location/options/forget).
The `--dry-run` flag will do a dry run showing what would have been deleted, but won't touch the actual data. The `--dry-run` flag will do a dry run showing what would have been deleted, but won't touch the actual data.
The `--prune` flag will also [prune the data](https://restic.readthedocs.io/en/latest/060_forget.html#removing-backup-snapshots). This is a costly operation that can take longer, however it will free up the actual space. The `--prune` flag will also [prune the data](https://restic.readthedocs.io/en/latest/060_forget.html#removing-backup-snapshots). This is a costly operation that can take longer, however it will free up the actual space.
> :ToCPrevNext

View File

@ -34,5 +34,3 @@ With `--restic-bin` you can specify to run a specific restic binary. This can be
```bash ```bash
autorestic --restic-bin /some/path/to/my/custom/restic/binary autorestic --restic-bin /some/path/to/my/custom/restic/binary
``` ```
> :ToCPrevNext

View File

@ -14,5 +14,3 @@ autorestic info
```bash ```bash
autorestic -c path/to/some/config.yml info autorestic -c path/to/some/config.yml info
``` ```
> :ToCPrevNext

View File

@ -5,5 +5,3 @@ Installs both restic and autorestic to `/usr/local/bin`.
```bash ```bash
autorestic install autorestic install
``` ```
> :ToCPrevNext

View File

@ -15,5 +15,3 @@ autorestic restore -l home --from hdd --to /path/where/to/restore
``` ```
This will restore the location `home` to the `/path/where/to/restore` folder and taking the data from the backend `hdd` This will restore the location `home` to the `/path/where/to/restore` folder and taking the data from the backend `hdd`
> :ToCPrevNext

View File

@ -5,5 +5,3 @@ Uninstalls both restic and autorestic from `/usr/local/bin`.
```bash ```bash
autorestic uninstall autorestic uninstall
``` ```
> :ToCPrevNext

32
docs/pages/cli/unlock.md Normal file
View File

@ -0,0 +1,32 @@
# Unlock
In case autorestic throws the error message `an instance is already running. exiting`, but there is no instance running you can unlock the lock.
To verify that there is no instance running you can use `ps aux | grep autorestic`.
Example with no instance running:
```bash
> ps aux | grep autorestic
root 39260 0.0 0.0 6976 2696 pts/11 S+ 19:41 0:00 grep autorestic
```
Example with an instance running:
```bash
> ps aux | grep autorestic
root 29465 0.0 0.0 1162068 7380 pts/7 Sl+ 19:28 0:00 autorestic --ci backup -a
root 39260 0.0 0.0 6976 2696 pts/11 S+ 19:41 0:00 grep autorestic
```
**If an instance is running you should not unlock as it could lead to data loss!**
```bash
autorestic unlock
```
Use the `--force` to prevent the confirmation prompt if an instance is running.
```bash
autorestic unlock --force
```

View File

@ -7,5 +7,3 @@ autorestic upgrade
``` ```
Updates both restic and autorestic automagically. Updates both restic and autorestic automagically.
> :ToCPrevNext

View File

@ -1,5 +1,7 @@
# 🏘 Community # 🏘 Community
## Software
A list of community driven projects. (No official affiliation) A list of community driven projects. (No official affiliation)
- SystemD Units: <https://gitlab.com/py_crash/autorestic-systemd-units> - SystemD Units: <https://gitlab.com/py_crash/autorestic-systemd-units>
@ -10,4 +12,6 @@ A list of community driven projects. (No official affiliation)
- Ansible Role: <https://0xacab.org/varac-projects/ansible-role-autorestic> - Ansible Role: <https://0xacab.org/varac-projects/ansible-role-autorestic>
- Ansible Role: <https://github.com/dbrennand/ansible-role-autorestic> - Ansible Role: <https://github.com/dbrennand/ansible-role-autorestic>
> :ToCPrevNext ## Writing
- [restic: excellent resource for local and cloud backup](https://notes.nicfab.eu/en/posts/restic/)

View File

@ -2,10 +2,11 @@
## Path ## Path
By default autorestic searches for a `.autorestic.yml` file in the current directory and your home folder. By default autorestic searches for a `.autorestic.yml` file in the current directory, your home folder and your XDG config folder (`~/.config/` by default):
- `./.autorestic.yml` - `./.autorestic.yml`
- `~/.autorestic.yml` - `~/.autorestic.yml`
- `~/.config/autorestic/.autorestic.yml`
You can also specify a custom file with the `-c path/to/some/config.yml` You can also specify a custom file with the `-c path/to/some/config.yml`
@ -55,6 +56,8 @@ version: 2
extras: extras:
hooks: &foo hooks: &foo
prevalidate:
- echo "Wake up!"
before: before:
- echo "Hello" - echo "Hello"
after: after:
@ -83,5 +86,3 @@ locations:
forget: forget:
<<: *bar <<: *bar
``` ```
> :ToCPrevNext

View File

@ -17,5 +17,3 @@ This amazing people helped the project!
- @TheForcer - Typos. - @TheForcer - Typos.
- @themorlan - Typos. - @themorlan - Typos.
- @somebox - Typos. - @somebox - Typos.
> :ToCPrevNext

View File

@ -36,5 +36,3 @@ locations:
to: to:
- somewhere-else - somewhere-else
``` ```
> :ToCPrevNext

View File

@ -13,10 +13,8 @@ Autorestic is a wrapper around the amazing [restic](https://restic.net/). While
- Backup locations to multiple backends - Backup locations to multiple backends
- Snapshot policies and pruning - Snapshot policies and pruning
- Fully encrypted - Fully encrypted
- Pre/After hooks - Before/after backup hooks
- Exclude pattern/files - Exclude pattern/files
- Cron jobs for automatic backup - Cron jobs for automatic backup
- Backup & Restore docker volumes - Backup & Restore docker volumes
- Generated completions for `[bash|zsh|fish|powershell]` - Generated completions for `[bash|zsh|fish|powershell]`
> :ToCPrevNext

View File

@ -24,8 +24,10 @@ You can download the right binary from the release page and simply copy it to `/
If you are on macOS you can install through brew: `brew install autorestic`. If you are on macOS you can install through brew: `brew install autorestic`.
### Fedora
Fedora users can install the [autorestic](https://src.fedoraproject.org/rpms/autorestic/) package with `dnf install autorestic`.
### AUR ### AUR
~~If you are on Arch there is an [AUR Package](https://aur.archlinux.org/packages/autorestic-bin/) (looking for maintainers).~~ - Deprecated If you are on Arch there is an [AUR Package](https://aur.archlinux.org/packages/autorestic-bin/)
> :ToCPrevNext

View File

@ -0,0 +1,7 @@
{
"index": "Overview",
"hooks": "Hooks",
"options": "Options",
"cron": "Cronjobs",
"docker": "Docker volumes"
}

View File

@ -1,6 +1,6 @@
# Cron # Cron
Often it is usefully to trigger backups automatically. For this we can specify a `cron` attribute to each location. Often it is useful to trigger backups automatically. For this, we can specify a `cron` attribute to each location.
```yaml | .autorestic.yml ```yaml | .autorestic.yml
locations: locations:
@ -10,15 +10,15 @@ locations:
cron: '0 3 * * 0' # Every Sunday at 3:00 cron: '0 3 * * 0' # Every Sunday at 3:00
``` ```
Here is a awesome website with [some examples](https://crontab.guru/examples.html) and an [explorer](https://crontab.guru/) Here is an awesome website with [some examples](https://crontab.guru/examples.html) and an [explorer](https://crontab.guru/).
## Installing the cron ## Installing the cron
**This has to be done only once, regardless of now many cron jobs you have in your config file.** **This has to be done only once, regardless of how many cron jobs you have in your config file.**
To actually enable cron jobs you need something to call `autorestic cron` on a timed schedule. To actually enable cron jobs you need something to call `autorestic cron` on a timed schedule.
Note that the schedule has nothing to do with the `cron` attribute in each location. Note that the schedule has nothing to do with the `cron` attribute in each location.
My advise would be to trigger the command every 5min, but if you have a cronjob that runs only once a week, it's probably enough to schedule it once a day. My advice would be to trigger the command every 5min, but if you have a cronjob that runs only once a week, it's probably enough to schedule it once a day.
### Crontab ### Crontab
@ -50,6 +50,4 @@ To debug a cron job you can use
Now you can add as many `cron` attributes as you wish in the config file ⏱ Now you can add as many `cron` attributes as you wish in the config file ⏱
> Also note that manually triggered backups with `autorestic backup` will not influence the cron timeline, they are willingly not linked. > Also note that manually triggered backups with `autorestic backup` will not influence the cron timeline, they are intentionally not linked.
> :ToCPrevNext

View File

@ -35,5 +35,3 @@ autorestic restore -l hello
``` ```
The volume has to exists whenever backing up or restoring. The volume has to exists whenever backing up or restoring.
> :ToCPrevNext

View File

@ -6,23 +6,28 @@ They consist of a list of commands that will be executed in the same directory a
The following hooks groups are supported, none are required: The following hooks groups are supported, none are required:
- `prevalidate`
- `before` - `before`
- `after` - `after`
- `failure` - `failure`
- `success` - `success`
The difference between `prevalidate` and `before` hooks are that `prevalidate` is run before checking the backup location is valid, including checking that the `from` directories exist. This can be useful, for example, to mount the source filesystem that contains the directories listed in `from`.
```yml | .autorestic.yml ```yml | .autorestic.yml
locations: locations:
my-location: my-location:
from: /data from: /data
to: my-backend to: my-backend
hooks: hooks:
prevalidate:
- echo "Checks"
before: before:
- echo "One" - echo "One"
- echo "Two" - echo "Two"
- echo "Three" - echo "Three"
after: after:
- echo "Byte" - echo "Bye"
failure: failure:
- echo "Something went wrong" - echo "Something went wrong"
success: success:
@ -31,13 +36,15 @@ locations:
## Flowchart ## Flowchart
1. `before` hook 1. `prevalidate` hook
2. Run backup 2. Check backup location
3. `after` hook 3. `before` hook
4. - `success` hook if no errors were found 4. Run backup
5. `after` hook
6. - `success` hook if no errors were found
- `failure` hook if at least one error was encountered - `failure` hook if at least one error was encountered
If the `before` hook encounters errors the backup and `after` hooks will be skipped and only the `failed` hooks will run. If either the `prevalidate` or `before` hook encounters errors then the backup and `after` hooks will be skipped and only the `failed` hooks will run.
## Environment variables ## Environment variables
@ -76,5 +83,3 @@ AUTORESTIC_LOCATION=bar
AUTORESTIC_FILES_ADDED_0=42 AUTORESTIC_FILES_ADDED_0=42
AUTORESTIC_FILES_ADDED_FOO=42 AUTORESTIC_FILES_ADDED_FOO=42
``` ```
> :ToCPrevNext

View File

@ -4,6 +4,7 @@ Locations can be seen as the input to the backup process. Generally this is simp
The paths can be relative from the config file. A location can have multiple backends, so that the data is secured across multiple servers. The paths can be relative from the config file. A location can have multiple backends, so that the data is secured across multiple servers.
Note: names of locations MUST be lower case! Note: names of locations MUST be lower case!
```yaml | .autorestic.yml ```yaml | .autorestic.yml
version: 2 version: 2
@ -30,5 +31,3 @@ Paths can be absolute or relative. If relative they are resolved relative to the
## `to` ## `to`
This is either a single backend or an array of backends. The backends have to be configured in the same config file. This is either a single backend or an array of backends. The backends have to be configured in the same config file.
> :ToCPrevNext

View File

@ -0,0 +1,3 @@
{
"index": "Overview"
}

View File

@ -16,5 +16,3 @@ locations:
- '*.abc' - '*.abc'
exclude-file: .gitignore exclude-file: .gitignore
``` ```
> :ToCPrevNext

View File

@ -53,5 +53,3 @@ locations:
forget: forget:
keep-last: 5 keep-last: 5
``` ```
> :ToCPrevNext

View File

@ -63,5 +63,3 @@ backends:
locations: locations:
# ... # ...
``` ```
> :ToCPrevNext

View File

@ -22,5 +22,3 @@ remote:
``` ```
Other than the config file there is a new `-v, --verbose` flag which shows the output of native commands, which are now hidden by default. Other than the config file there is a new `-v, --verbose` flag which shows the output of native commands, which are now hidden by default.
> :ToCPrevNext

View File

@ -64,5 +64,3 @@ Autorestic changed the way backups are referenced. Before we took the paths as t
```bash ```bash
autorestic exec -va -- tag --add ar:location:LOCATION_NAME # Only if you have only one location autorestic exec -va -- tag --add ar:location:LOCATION_NAME # Only if you have only one location
``` ```
> :ToCPrevNext

View File

@ -0,0 +1,4 @@
{
"0.x_1.0": "0.x → 1.0",
"1.4_1.5": "1.4 → 1.5"
}

View File

@ -6,5 +6,3 @@ This happens when autorestic needs to write to the config file: e.g. when we are
Unfortunately during this process formatting and comments are lost because the `yaml` library used is not comment and/or format aware. Unfortunately during this process formatting and comments are lost because the `yaml` library used is not comment and/or format aware.
That is why autorestic will place a copy of your old config next to the one we are writing to. That is why autorestic will place a copy of your old config next to the one we are writing to.
> :ToCPrevNext

View File

@ -82,5 +82,3 @@ autorestic restore -l home --from hdd --to /path/where/to/restore
``` ```
This will restore the location `home` from the backend `hdd` to the given path. This will restore the location `home` from the backend `hdd` to the given path.
> :ToCPrevNext

3044
docs/pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

24
docs/theme.config.jsx Normal file
View File

@ -0,0 +1,24 @@
export default {
logo: <span>Autorestic</span>,
docsRepositoryBase: 'https://github.com/cupcakearmy/autorestic/tree/master/docs',
project: {
link: 'https://github.com/cupcakearmy/autorestic',
},
sidebar: {
defaultMenuCollapseLevel: 1,
},
feedback: {
content: 'Question? An error? Give feedback →',
},
footer: {
text: (
<span>
MIT {new Date().getFullYear()} ©{' '}
<a href="https://github.com/cupcakearmy" target="_blank">
cupcakearmy
</a>
.
</span>
),
},
}

View File

@ -1,3 +0,0 @@
{
"cleanUrls": true
}

4
go.mod
View File

@ -1,6 +1,6 @@
module github.com/cupcakearmy/autorestic module github.com/cupcakearmy/autorestic
go 1.18 go 1.21
require ( require (
github.com/blang/semver/v4 v4.0.0 github.com/blang/semver/v4 v4.0.0
@ -32,5 +32,5 @@ require (
golang.org/x/text v0.3.8 // indirect golang.org/x/text v0.3.8 // indirect
gopkg.in/ini.v1 v1.66.4 // indirect gopkg.in/ini.v1 v1.66.4 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect gopkg.in/yaml.v3 v3.0.0 // indirect
) )

4
go.sum
View File

@ -487,8 +487,8 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -143,6 +143,7 @@ func (b Backend) Exec(args []string) error {
return err return err
} }
options := ExecuteOptions{Envs: env} options := ExecuteOptions{Envs: env}
args = append(args, combineBackendOptions("exec", b)...)
_, out, err := ExecuteResticCommand(options, args...) _, out, err := ExecuteResticCommand(options, args...)
if err != nil { if err != nil {
colors.Error.Println(out) colors.Error.Println(out)
@ -182,6 +183,7 @@ func (b Backend) ExecDocker(l Location, args []string) (int, string, error) {
case "s3": case "s3":
case "azure": case "azure":
case "gs": case "gs":
case "rest":
// No additional setup needed // No additional setup needed
case "rclone": case "rclone":
// Read host rclone config and mount it into the container // Read host rclone config and mount it into the container

View File

@ -6,7 +6,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net/http" "net/http"
"os" "os"
"path" "path"
@ -37,7 +36,7 @@ func dlJSON(url string) (GithubRelease, error) {
return parsed, err return parsed, err
} }
defer resp.Body.Close() defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
return parsed, err return parsed, err
@ -73,9 +72,10 @@ func downloadAndInstallAsset(body GithubRelease, name string) error {
// Uncompress // Uncompress
bz := bzip2.NewReader(resp.Body) bz := bzip2.NewReader(resp.Body)
// Save to tmp // Save to tmp file in the same directory as the install directory
// Linux does not support overwriting the file that is currently being overwritten, but it can be deleted and a new one moved in its place. // Linux does not support overwriting the file that is currently being running
tmp, err := ioutil.TempFile(os.TempDir(), "autorestic-") // But it can be delete the old one and a new one moved in its place.
tmp, err := os.CreateTemp(INSTALL_PATH, "autorestic-")
if err != nil { if err != nil {
return err return err
} }
@ -89,24 +89,26 @@ func downloadAndInstallAsset(body GithubRelease, name string) error {
to := path.Join(INSTALL_PATH, name) to := path.Join(INSTALL_PATH, name)
defer os.Remove(tmp.Name()) // Cleanup temporary file after thread exits defer os.Remove(tmp.Name()) // Cleanup temporary file after thread exits
if err := os.Rename(tmp.Name(), to); err != nil {
colors.Error.Printf("os.Rename() failed (%v), retrying with io.Copy()\n", err.Error()) mode := os.FileMode(0755)
var src *os.File if originalBin, err := os.Lstat(to); err == nil {
var dst *os.File mode = originalBin.Mode()
if src, err = os.Open(tmp.Name()); err != nil { err := os.Remove(to)
return err if err != nil {
}
if dst, err = os.Create(to); err != nil {
return err
}
if _, err := io.Copy(dst, src); err != nil {
return err
}
if err := os.Chmod(to, 0755); err != nil {
return err return err
} }
} }
err = os.Rename(tmp.Name(), to)
if err != nil {
return err
}
err = os.Chmod(to, mode)
if err != nil {
return err
}
colors.Success.Printf("Successfully installed '%s' under %s\n", name, INSTALL_PATH) colors.Success.Printf("Successfully installed '%s' under %s\n", name, INSTALL_PATH)
return nil return nil
} }

View File

@ -17,7 +17,7 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
) )
const VERSION = "1.7.6" const VERSION = "1.8.2"
type OptionMap map[string][]interface{} type OptionMap map[string][]interface{}
type Options map[string]OptionMap type Options map[string]OptionMap
@ -132,10 +132,11 @@ func (c *Config) Describe() {
tmp = "" tmp = ""
hooks := map[string][]string{ hooks := map[string][]string{
"Before": l.Hooks.Before, "PreValidate": l.Hooks.PreValidate,
"After": l.Hooks.After, "Before": l.Hooks.Before,
"Failure": l.Hooks.Failure, "After": l.Hooks.After,
"Success": l.Hooks.Success, "Failure": l.Hooks.Failure,
"Success": l.Hooks.Success,
} }
for hook, commands := range hooks { for hook, commands := range hooks {
if len(commands) > 0 { if len(commands) > 0 {

View File

@ -33,11 +33,12 @@ const (
) )
type Hooks struct { type Hooks struct {
Dir string `mapstructure:"dir"` Dir string `mapstructure:"dir"`
Before HookArray `mapstructure:"before,omitempty"` PreValidate HookArray `mapstructure:"prevalidate,omitempty"`
After HookArray `mapstructure:"after,omitempty"` Before HookArray `mapstructure:"before,omitempty"`
Success HookArray `mapstructure:"success,omitempty"` After HookArray `mapstructure:"after,omitempty"`
Failure HookArray `mapstructure:"failure,omitempty"` Success HookArray `mapstructure:"success,omitempty"`
Failure HookArray `mapstructure:"failure,omitempty"`
} }
type LocationCopy = map[string][]string type LocationCopy = map[string][]string
@ -184,12 +185,18 @@ func (l Location) Backup(cron bool, specificBackend string) []error {
}, },
} }
// Hooks before location validation
if err := l.ExecuteHooks(l.Hooks.PreValidate, options); err != nil {
errors = append(errors, err)
goto after
}
if err := l.validate(); err != nil { if err := l.validate(); err != nil {
errors = append(errors, err) errors = append(errors, err)
goto after goto after
} }
// Hooks // Hooks after location validation
if err := l.ExecuteHooks(l.Hooks.Before, options); err != nil { if err := l.ExecuteHooks(l.Hooks.Before, options); err != nil {
errors = append(errors, err) errors = append(errors, err)
goto after goto after
@ -289,12 +296,13 @@ func (l Location) Backup(cron bool, specificBackend string) []error {
} }
} }
// After hooks // After backup hooks
if err := l.ExecuteHooks(l.Hooks.After, options); err != nil { if err := l.ExecuteHooks(l.Hooks.After, options); err != nil {
errors = append(errors, err) errors = append(errors, err)
} }
after: after:
// Success/failure hooks
var commands []string var commands []string
var isSuccess = len(errors) == 0 var isSuccess = len(errors) == 0
if isSuccess { if isSuccess {

View File

@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,