Compare commits

..

1 Commits

Author SHA1 Message Date
Andreas Wagner
4e3ae6403b add more architectures for linux build process
equivalent to 7d665fa1f4/helpers/build-release-binaries/main.go
2022-10-06 12:06:20 +03:00
24 changed files with 8090 additions and 3889 deletions

View File

@@ -1,8 +0,0 @@
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"

View File

@@ -10,12 +10,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v1
- name: Docker Labels - name: Docker Labels
id: meta id: meta
uses: crazy-max/ghaction-docker-meta@v4 uses: crazy-max/ghaction-docker-meta@v2
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@v2 uses: docker/login-action@v1
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@v3 uses: docker/build-push-action@v2
with: with:
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
push: true push: true
@@ -37,12 +37,17 @@ jobs:
release: release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
- uses: actions/setup-go@v3 - uses: actions/setup-go@v2
with: with:
go-version: "^1.20" go-version: "^1.16.3"
- 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

@@ -5,17 +5,6 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.7.4] - 2023-01-18
### Fixed
- Transformer for extracting information. @11mariom
### Changed
- Bump docker restic version.
- Docs dependencies updated.
## [1.7.1] - 2022-04-27 ## [1.7.1] - 2022-04-27
### Fixed ### Fixed

View File

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

View File

@@ -4,11 +4,7 @@
package main package main
import ( import (
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path" "path"
@@ -21,51 +17,23 @@ import (
var DIR, _ = filepath.Abs("./dist") var DIR, _ = filepath.Abs("./dist")
var targets = map[string][]string{ var targets = map[string][]string{
// "aix": {"ppc64"}, // Not supported by fsnotify
"darwin": {"amd64", "arm64"}, "darwin": {"amd64", "arm64"},
"freebsd": {"386", "amd64", "arm"}, "freebsd": {"386", "amd64", "arm"},
"linux": {"386", "amd64", "arm", "arm64", "ppc64le", "mips", "mipsle", "mips64", "mips64le", "s390x"}, "linux": {"386", "amd64", "arm", "arm64", "ppc64le", "mips", "mipsle", "mips64", "mips64le"},
"netbsd": {"386", "amd64"}, "netbsd": {"386", "amd64"},
"openbsd": {"386", "amd64"}, "openbsd": {"386", "amd64"},
// "windows": {"386", "amd64"}, // Not supported by autorestic
"solaris": {"amd64"},
} }
type buildOptions struct { type buildOptions struct {
Target, Arch, Version string Target, Arch, Version string
} }
const ( func build(options buildOptions, wg *sync.WaitGroup) {
CHECKSUM_MD5 = "MD5SUMS" fmt.Printf("Building %s %s\n", options.Target, options.Arch)
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
{ {
@@ -94,39 +62,22 @@ func build(options buildOptions, wg *sync.WaitGroup, checksums *[]Checksums) {
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)
go build(buildOptions{ build(buildOptions{
Target: target, Target: target,
Arch: arch, Arch: arch,
Version: v, Version: v,
}, &wg, &checksums) }, &wg)
} }
} }
wg.Wait() wg.Wait()
writeChecksums(&checksums)
} }

View File

@@ -5,10 +5,10 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/cupcakearmy/autorestic/internal"
"github.com/cupcakearmy/autorestic/internal/colors" "github.com/cupcakearmy/autorestic/internal/colors"
"github.com/cupcakearmy/autorestic/internal/flags" "github.com/cupcakearmy/autorestic/internal/flags"
"github.com/cupcakearmy/autorestic/internal/lock" "github.com/cupcakearmy/autorestic/internal/lock"
"github.com/cupcakearmy/autorestic/internal/version"
"github.com/spf13/cobra" "github.com/spf13/cobra"
homedir "github.com/mitchellh/go-homedir" homedir "github.com/mitchellh/go-homedir"
@@ -26,7 +26,7 @@ func CheckErr(err error) {
var cfgFile string var cfgFile string
var rootCmd = &cobra.Command{ var rootCmd = &cobra.Command{
Version: version.VERSION, Version: internal.VERSION,
Use: "autorestic", Use: "autorestic",
Short: "CLI Wrapper for restic", Short: "CLI Wrapper for restic",
Long: "Documentation:\thttps://autorestic.vercel.app\nSupport:\thttps://discord.gg/wS7RpYTYd2", Long: "Documentation:\thttps://autorestic.vercel.app\nSupport:\thttps://discord.gg/wS7RpYTYd2",
@@ -41,7 +41,7 @@ func init() {
rootCmd.PersistentFlags().BoolVar(&flags.CI, "ci", false, "CI mode disabled interactive mode and colors and enables verbosity") rootCmd.PersistentFlags().BoolVar(&flags.CI, "ci", false, "CI mode disabled interactive mode and colors and enables verbosity")
rootCmd.PersistentFlags().BoolVarP(&flags.VERBOSE, "verbose", "v", false, "verbose mode") rootCmd.PersistentFlags().BoolVarP(&flags.VERBOSE, "verbose", "v", false, "verbose mode")
rootCmd.PersistentFlags().StringVar(&flags.RESTIC_BIN, "restic-bin", "restic", "specify custom restic binary") rootCmd.PersistentFlags().StringVar(&flags.RESTIC_BIN, "restic-bin", "restic", "specify custom restic binary")
rootCmd.PersistentFlags().StringVar(&flags.DOCKER_IMAGE, "docker-image", "cupcakearmy/autorestic:"+version.VERSION, "specify a custom docker image") rootCmd.PersistentFlags().StringVar(&flags.DOCKER_IMAGE, "docker-image", "cupcakearmy/autorestic:"+internal.VERSION, "specify a custom docker image")
cobra.OnInitialize(initConfig) cobra.OnInitialize(initConfig)
} }
@@ -55,7 +55,7 @@ func initConfig() {
viper.SetConfigFile(cfgFile) viper.SetConfigFile(cfgFile)
viper.AutomaticEnv() viper.AutomaticEnv()
if viper.ConfigFileUsed() == "" { if viper.ConfigFileUsed() == "" {
colors.Error.Printf("cannot read config file %s\n", cfgFile) colors.Error.Println("cannot read config file %s\n", cfgFile)
os.Exit(1) os.Exit(1)
} }
} else { } else {

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -8,6 +8,5 @@ A list of community driven projects. (No official affiliation)
- Ansible Role: <https://github.com/ItsNotGoodName/ansible-role-autorestic> - Ansible Role: <https://github.com/ItsNotGoodName/ansible-role-autorestic>
- Ansible Role: <https://github.com/FuzzyMistborn/ansible-role-autorestic> - Ansible Role: <https://github.com/FuzzyMistborn/ansible-role-autorestic>
- 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>
> :ToCPrevNext > :ToCPrevNext

View File

@@ -5,7 +5,7 @@ Linux & macOS. Windows is not supported. If you have problems installing please
Autorestic requires `bash`, `wget` and `bzip2` to be installed. For most systems these should be already installed. Autorestic requires `bash`, `wget` and `bzip2` to be installed. For most systems these should be already installed.
```bash ```bash
wget -qO - https://raw.githubusercontent.com/cupcakearmy/autorestic/master/install.sh | bash wget -qO - https://raw.githubusercontent.com/CupCakeArmy/autorestic/master/install.sh | bash
``` ```
## Alternatives ## Alternatives
@@ -24,10 +24,6 @@ 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/) (looking for maintainers).~~ - Deprecated

View File

@@ -3,7 +3,7 @@
## Installation ## Installation
```bash ```bash
wget -qO - https://raw.githubusercontent.com/cupcakearmy/autorestic/master/install.sh | bash wget -qO - https://raw.githubusercontent.com/CupCakeArmy/autorestic/master/install.sh | bash
``` ```
See [installation](/installation) for alternative options. See [installation](/installation) for alternative options.

1870
docs/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,6 @@
"dev": "codedoc serve" "dev": "codedoc serve"
}, },
"dependencies": { "dependencies": {
"@codedoc/cli": "^0.3.0" "@codedoc/cli": "^0.2.8"
} }
} }

6
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/cupcakearmy/autorestic module github.com/cupcakearmy/autorestic
go 1.20 go 1.18
require ( require (
github.com/blang/semver/v4 v4.0.0 github.com/blang/semver/v4 v4.0.0
@@ -28,8 +28,8 @@ require (
github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.2.0 // indirect github.com/subosito/gotenv v1.2.0 // indirect
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
golang.org/x/text v0.3.8 // indirect golang.org/x/text v0.3.7 // 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-20210107192922-496545a6307b // indirect

8
go.sum
View File

@@ -324,8 +324,8 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -333,8 +333,8 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

View File

@@ -31,11 +31,6 @@ else
fi fi
echo $ARCH echo $ARCH
if ! command -v bzip2 &>/dev/null; then
echo "Missing bzip2 command. Please install the bzip2 package for your system."
exit 1
fi
wget -qO - https://api.github.com/repos/cupcakearmy/autorestic/releases/latest \ wget -qO - https://api.github.com/repos/cupcakearmy/autorestic/releases/latest \
| grep "browser_download_url.*_${OS}_${ARCH}" \ | grep "browser_download_url.*_${OS}_${ARCH}" \
| cut -d : -f 2,3 \ | cut -d : -f 2,3 \

View File

@@ -10,8 +10,6 @@ import (
"github.com/cupcakearmy/autorestic/internal/colors" "github.com/cupcakearmy/autorestic/internal/colors"
"github.com/cupcakearmy/autorestic/internal/flags" "github.com/cupcakearmy/autorestic/internal/flags"
"github.com/cupcakearmy/autorestic/internal/options"
"github.com/cupcakearmy/autorestic/internal/utils"
) )
type BackendRest struct { type BackendRest struct {
@@ -26,7 +24,7 @@ type Backend struct {
Key string `mapstructure:"key,omitempty"` Key string `mapstructure:"key,omitempty"`
Env map[string]string `mapstructure:"env,omitempty"` Env map[string]string `mapstructure:"env,omitempty"`
Rest BackendRest `mapstructure:"rest,omitempty"` Rest BackendRest `mapstructure:"rest,omitempty"`
Options options.Options `mapstructure:"options,omitempty"` Options Options `mapstructure:"options,omitempty"`
} }
func GetBackend(name string) (Backend, bool) { func GetBackend(name string) (Backend, bool) {
@@ -40,7 +38,7 @@ func (b Backend) generateRepo() (string, error) {
case "local": case "local":
return GetPathRelativeToConfig(b.Path) return GetPathRelativeToConfig(b.Path)
case "rest": case "rest":
parsed, err := url.Parse(os.ExpandEnv(b.Path)) parsed, err := url.Parse(b.Path)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -122,15 +120,11 @@ func (b Backend) validate() error {
if err != nil { if err != nil {
return err return err
} }
options := utils.ExecuteOptions{ options := ExecuteOptions{Envs: env, Silent: true}
Envs: env,
Silent: true,
Global: GetConfig().Global,
}
// Check if already initialized // Check if already initialized
cmd := []string{"check"} cmd := []string{"check"}
cmd = append(cmd, combineBackendOptions("check", b)...) cmd = append(cmd, combineBackendOptions("check", b)...)
_, _, err = utils.ExecuteResticCommand(options, cmd...) _, _, err = ExecuteResticCommand(options, cmd...)
if err == nil { if err == nil {
return nil return nil
} else { } else {
@@ -138,7 +132,7 @@ func (b Backend) validate() error {
colors.Body.Printf("Initializing backend \"%s\"...\n", b.name) colors.Body.Printf("Initializing backend \"%s\"...\n", b.name)
cmd := []string{"init"} cmd := []string{"init"}
cmd = append(cmd, combineBackendOptions("init", b)...) cmd = append(cmd, combineBackendOptions("init", b)...)
_, _, err := utils.ExecuteResticCommand(options, cmd...) _, _, err := ExecuteResticCommand(options, cmd...)
return err return err
} }
} }
@@ -148,11 +142,8 @@ func (b Backend) Exec(args []string) error {
if err != nil { if err != nil {
return err return err
} }
options := utils.ExecuteOptions{ options := ExecuteOptions{Envs: env}
Envs: env, _, out, err := ExecuteResticCommand(options, args...)
Global: GetConfig().Global,
}
_, out, err := utils.ExecuteResticCommand(options, args...)
if err != nil { if err != nil {
colors.Error.Println(out) colors.Error.Println(out)
return err return err
@@ -166,7 +157,7 @@ func (b Backend) ExecDocker(l Location, args []string) (int, string, error) {
return -1, "", err return -1, "", err
} }
volume := l.From[0] volume := l.From[0]
options := utils.ExecuteOptions{ options := ExecuteOptions{
Command: "docker", Command: "docker",
Envs: env, Envs: env,
} }
@@ -194,7 +185,7 @@ func (b Backend) ExecDocker(l Location, args []string) (int, string, error) {
// 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
code, configFile, err := utils.ExecuteCommand(utils.ExecuteOptions{Command: "rclone"}, "config", "file") code, configFile, err := ExecuteCommand(ExecuteOptions{Command: "rclone"}, "config", "file")
if err != nil { if err != nil {
return code, "", err return code, "", err
} }
@@ -209,5 +200,5 @@ func (b Backend) ExecDocker(l Location, args []string) (int, string, error) {
} }
docker = append(docker, flags.DOCKER_IMAGE, "-c", strings.Join(args, " ")) docker = append(docker, flags.DOCKER_IMAGE, "-c", strings.Join(args, " "))
return utils.ExecuteCommand(options, docker...) return ExecuteCommand(options, docker...)
} }

View File

@@ -14,10 +14,9 @@ import (
"strings" "strings"
"github.com/blang/semver/v4" "github.com/blang/semver/v4"
"github.com/cupcakearmy/autorestic/internal"
"github.com/cupcakearmy/autorestic/internal/colors" "github.com/cupcakearmy/autorestic/internal/colors"
"github.com/cupcakearmy/autorestic/internal/flags" "github.com/cupcakearmy/autorestic/internal/flags"
"github.com/cupcakearmy/autorestic/internal/utils"
"github.com/cupcakearmy/autorestic/internal/version"
) )
const INSTALL_PATH = "/usr/local/bin" const INSTALL_PATH = "/usr/local/bin"
@@ -116,7 +115,7 @@ func downloadAndInstallAsset(body GithubRelease, name string) error {
} }
func InstallRestic() error { func InstallRestic() error {
installed := utils.CheckIfCommandIsCallable("restic") installed := internal.CheckIfCommandIsCallable("restic")
if installed { if installed {
colors.Body.Println("restic already installed") colors.Body.Println("restic already installed")
return nil return nil
@@ -130,7 +129,7 @@ func InstallRestic() error {
} }
func upgradeRestic() error { func upgradeRestic() error {
_, _, err := utils.ExecuteCommand(utils.ExecuteOptions{ _, _, err := internal.ExecuteCommand(internal.ExecuteOptions{
Command: flags.RESTIC_BIN, Command: flags.RESTIC_BIN,
}, "self-update") }, "self-update")
return err return err
@@ -148,7 +147,7 @@ func Upgrade(restic bool) error {
} }
// Upgrade self // Upgrade self
current, err := semver.ParseTolerant(version.VERSION) current, err := semver.ParseTolerant(internal.VERSION)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -11,20 +11,23 @@ import (
"github.com/cupcakearmy/autorestic/internal/colors" "github.com/cupcakearmy/autorestic/internal/colors"
"github.com/cupcakearmy/autorestic/internal/flags" "github.com/cupcakearmy/autorestic/internal/flags"
"github.com/cupcakearmy/autorestic/internal/lock" "github.com/cupcakearmy/autorestic/internal/lock"
"github.com/cupcakearmy/autorestic/internal/options"
"github.com/cupcakearmy/autorestic/internal/utils"
"github.com/joho/godotenv" "github.com/joho/godotenv"
"github.com/mitchellh/go-homedir" "github.com/mitchellh/go-homedir"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
const VERSION = "1.7.3"
type OptionMap map[string][]interface{}
type Options map[string]OptionMap
type Config struct { type Config struct {
Version string `mapstructure:"version"` Version string `mapstructure:"version"`
Extras interface{} `mapstructure:"extras"` Extras interface{} `mapstructure:"extras"`
Locations map[string]Location `mapstructure:"locations"` Locations map[string]Location `mapstructure:"locations"`
Backends map[string]Backend `mapstructure:"backends"` Backends map[string]Backend `mapstructure:"backends"`
Global options.Options `mapstructure:"global"` Global Options `mapstructure:"global"`
} }
var once sync.Once var once sync.Once
@@ -181,7 +184,7 @@ func CheckConfig() error {
if c == nil { if c == nil {
return fmt.Errorf("config could not be loaded/found") return fmt.Errorf("config could not be loaded/found")
} }
if !utils.CheckIfResticIsCallable() { if !CheckIfResticIsCallable() {
return fmt.Errorf(`%s was not found. Install either with "autorestic install" or manually`, flags.RESTIC_BIN) return fmt.Errorf(`%s was not found. Install either with "autorestic install" or manually`, flags.RESTIC_BIN)
} }
for name, backend := range c.Backends { for name, backend := range c.Backends {
@@ -260,7 +263,7 @@ func AddFlagsToCommand(cmd *cobra.Command, backend bool) {
func (c *Config) SaveConfig() error { func (c *Config) SaveConfig() error {
file := viper.ConfigFileUsed() file := viper.ConfigFileUsed()
if err := utils.CopyFile(file, file+".old"); err != nil { if err := CopyFile(file, file+".old"); err != nil {
return err return err
} }
colors.Secondary.Println("Saved a backup copy of your file next to the original.") colors.Secondary.Println("Saved a backup copy of your file next to the original.")
@@ -271,11 +274,40 @@ func (c *Config) SaveConfig() error {
return viper.WriteConfig() return viper.WriteConfig()
} }
func optionToString(option string) string {
if !strings.HasPrefix(option, "-") {
return "--" + option
}
return option
}
func appendOptionsToSlice(str *[]string, options OptionMap) {
for key, values := range options {
for _, value := range values {
// Bool
asBool, ok := value.(bool)
if ok && asBool {
*str = append(*str, optionToString(key))
continue
}
*str = append(*str, optionToString(key), fmt.Sprint(value))
}
}
}
func getOptions(options Options, keys []string) []string {
var selected []string
for _, key := range keys {
appendOptionsToSlice(&selected, options[key])
}
return selected
}
func combineBackendOptions(key string, b Backend) []string { func combineBackendOptions(key string, b Backend) []string {
// Priority: backend > global // Priority: backend > global
var options []string var options []string
gFlags := GetConfig().Global.GetOptions([]string{key}) gFlags := getOptions(GetConfig().Global, []string{key})
bFlags := b.Options.GetOptions([]string{"all", key}) bFlags := getOptions(b.Options, []string{"all", key})
options = append(options, gFlags...) options = append(options, gFlags...)
options = append(options, bFlags...) options = append(options, bFlags...)
return options return options
@@ -284,9 +316,9 @@ func combineBackendOptions(key string, b Backend) []string {
func combineAllOptions(key string, l Location, b Backend) []string { func combineAllOptions(key string, l Location, b Backend) []string {
// Priority: location > backend > global // Priority: location > backend > global
var options []string var options []string
gFlags := GetConfig().Global.GetOptions([]string{key}) gFlags := getOptions(GetConfig().Global, []string{key})
bFlags := b.Options.GetOptions([]string{"all", key}) bFlags := getOptions(b.Options, []string{"all", key})
lFlags := l.Options.GetOptions([]string{"all", key}) lFlags := getOptions(l.Options, []string{"all", key})
options = append(options, gFlags...) options = append(options, gFlags...)
options = append(options, bFlags...) options = append(options, bFlags...)
options = append(options, lFlags...) options = append(options, lFlags...)

View File

@@ -12,8 +12,6 @@ import (
"github.com/cupcakearmy/autorestic/internal/flags" "github.com/cupcakearmy/autorestic/internal/flags"
"github.com/cupcakearmy/autorestic/internal/lock" "github.com/cupcakearmy/autorestic/internal/lock"
"github.com/cupcakearmy/autorestic/internal/metadata" "github.com/cupcakearmy/autorestic/internal/metadata"
"github.com/cupcakearmy/autorestic/internal/utils"
"github.com/cupcakearmy/autorestic/internal/options"
"github.com/robfig/cron" "github.com/robfig/cron"
) )
@@ -51,7 +49,7 @@ type Location struct {
To []string `mapstructure:"to,omitempty"` To []string `mapstructure:"to,omitempty"`
Hooks Hooks `mapstructure:"hooks,omitempty"` Hooks Hooks `mapstructure:"hooks,omitempty"`
Cron string `mapstructure:"cron,omitempty"` Cron string `mapstructure:"cron,omitempty"`
Options options.Options `mapstructure:"options,omitempty"` Options Options `mapstructure:"options,omitempty"`
ForgetOption LocationForgetOption `mapstructure:"forget,omitempty"` ForgetOption LocationForgetOption `mapstructure:"forget,omitempty"`
CopyOption LocationCopy `mapstructure:"copy,omitempty"` CopyOption LocationCopy `mapstructure:"copy,omitempty"`
} }
@@ -103,14 +101,14 @@ func (l Location) validate() error {
if _, ok := GetBackend(copyFrom); !ok { if _, ok := GetBackend(copyFrom); !ok {
return fmt.Errorf(`location "%s" has an invalid backend "%s" in copy option`, l.name, copyFrom) return fmt.Errorf(`location "%s" has an invalid backend "%s" in copy option`, l.name, copyFrom)
} }
if !utils.ArrayContains(l.To, copyFrom) { if !ArrayContains(l.To, copyFrom) {
return fmt.Errorf(`location "%s" has an invalid copy from "%s"`, l.name, copyFrom) return fmt.Errorf(`location "%s" has an invalid copy from "%s"`, l.name, copyFrom)
} }
for _, copyToTarget := range copyTo { for _, copyToTarget := range copyTo {
if _, ok := GetBackend(copyToTarget); !ok { if _, ok := GetBackend(copyToTarget); !ok {
return fmt.Errorf(`location "%s" has an invalid backend "%s" in copy option`, l.name, copyToTarget) return fmt.Errorf(`location "%s" has an invalid backend "%s" in copy option`, l.name, copyToTarget)
} }
if utils.ArrayContains(l.To, copyToTarget) { if ArrayContains(l.To, copyToTarget) {
return fmt.Errorf(`location "%s" cannot copy to "%s" as it's already a target`, l.name, copyToTarget) return fmt.Errorf(`location "%s" cannot copy to "%s" as it's already a target`, l.name, copyToTarget)
} }
} }
@@ -125,7 +123,7 @@ func (l Location) validate() error {
return nil return nil
} }
func (l Location) ExecuteHooks(commands []string, options utils.ExecuteOptions) error { func (l Location) ExecuteHooks(commands []string, options ExecuteOptions) error {
if len(commands) == 0 { if len(commands) == 0 {
return nil return nil
} }
@@ -139,7 +137,7 @@ func (l Location) ExecuteHooks(commands []string, options utils.ExecuteOptions)
colors.Secondary.Println("\nRunning hooks") colors.Secondary.Println("\nRunning hooks")
for _, command := range commands { for _, command := range commands {
colors.Body.Println("> " + command) colors.Body.Println("> " + command)
_, out, err := utils.ExecuteCommand(options, "-c", command) _, out, err := ExecuteCommand(options, "-c", command)
if err != nil { if err != nil {
colors.Error.Println(out) colors.Error.Println(out)
return err return err
@@ -178,7 +176,7 @@ func (l Location) Backup(cron bool, specificBackend string) []error {
return errors return errors
} }
cwd, _ := GetPathRelativeToConfig(".") cwd, _ := GetPathRelativeToConfig(".")
options := utils.ExecuteOptions{ options := ExecuteOptions{
Command: "bash", Command: "bash",
Dir: cwd, Dir: cwd,
Envs: map[string]string{ Envs: map[string]string{
@@ -223,9 +221,8 @@ func (l Location) Backup(cron bool, specificBackend string) []error {
cmd = append(cmd, "--tag", buildTag("cron")) cmd = append(cmd, "--tag", buildTag("cron"))
} }
cmd = append(cmd, "--tag", l.getLocationTags()) cmd = append(cmd, "--tag", l.getLocationTags())
backupOptions := utils.ExecuteOptions{ backupOptions := ExecuteOptions{
Envs: env, Envs: env,
Global: GetConfig().Global,
} }
var code int = 0 var code int = 0
@@ -240,9 +237,9 @@ func (l Location) Backup(cron bool, specificBackend string) []error {
} }
cmd = append(cmd, path) cmd = append(cmd, path)
} }
code, out, err = utils.ExecuteResticCommand(backupOptions, cmd...) code, out, err = ExecuteResticCommand(backupOptions, cmd...)
case TypeVolume: case TypeVolume:
ok := utils.CheckIfVolumeExists(l.From[0]) ok := CheckIfVolumeExists(l.From[0])
if !ok { if !ok {
errors = append(errors, fmt.Errorf("volume \"%s\" does not exist", l.From[0])) errors = append(errors, fmt.Errorf("volume \"%s\" does not exist", l.From[0]))
continue continue
@@ -280,9 +277,8 @@ func (l Location) Backup(cron bool, specificBackend string) []error {
for k, v := range env2 { for k, v := range env2 {
env[k+"2"] = v env[k+"2"] = v
} }
_, _, err := utils.ExecuteResticCommand(utils.ExecuteOptions{ _, _, err := ExecuteResticCommand(ExecuteOptions{
Envs: env, Envs: env,
Global: GetConfig().Global,
}, "copy", md.SnapshotID) }, "copy", md.SnapshotID)
if err != nil { if err != nil {
@@ -312,10 +308,7 @@ after:
// Forget and optionally prune // Forget and optionally prune
if isSuccess && l.ForgetOption != "" && l.ForgetOption != LocationForgetNo { if isSuccess && l.ForgetOption != "" && l.ForgetOption != LocationForgetNo {
err := l.Forget(l.ForgetOption == LocationForgetPrune, false) l.Forget(l.ForgetOption == LocationForgetPrune, false)
if err != nil {
errors = append(errors, err)
}
} }
if len(errors) == 0 { if len(errors) == 0 {
@@ -339,9 +332,8 @@ func (l Location) Forget(prune bool, dry bool) error {
if err != nil { if err != nil {
return nil return nil
} }
options := utils.ExecuteOptions{ options := ExecuteOptions{
Envs: env, Envs: env,
Global: GetConfig().Global,
} }
cmd := []string{"forget", "--tag", l.getLocationTags()} cmd := []string{"forget", "--tag", l.getLocationTags()}
if prune { if prune {
@@ -351,7 +343,7 @@ func (l Location) Forget(prune bool, dry bool) error {
cmd = append(cmd, "--dry-run") cmd = append(cmd, "--dry-run")
} }
cmd = append(cmd, combineAllOptions("forget", l, backend)...) cmd = append(cmd, combineAllOptions("forget", l, backend)...)
_, _, err = utils.ExecuteResticCommand(options, cmd...) _, _, err = ExecuteResticCommand(options, cmd...)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -14,9 +14,9 @@ func (e addedExtractor) Matches(line string) bool {
} }
func (e addedExtractor) Extract(metadata *BackupLogMetadata, line string) { func (e addedExtractor) Extract(metadata *BackupLogMetadata, line string) {
// Sample line: "Added to the repo: 0 B" // Sample line: "Added to the repo: 0 B"
metadata.AddedSize = strings.TrimSpace(e.re.ReplaceAllString(line, "$2")) metadata.AddedSize = strings.TrimSpace(e.re.ReplaceAllString(line, ""))
} }
func NewAddedExtractor() MetadatExtractor { func NewAddedExtractor() MetadatExtractor {
return addedExtractor{regexp.MustCompile(`(?i)^Added to the repo(sitory)?: ([\d\.]+ \w+)( \([\d\.]+[\w\s]+\))?`)} return addedExtractor{regexp.MustCompile(`(?i)^Added to the repo:`)}
} }

View File

@@ -1,38 +0,0 @@
package options
import (
"fmt"
"strings"
)
type OptionMap map[string][]interface{}
type Options map[string]OptionMap
func (o Options) GetOptions(keys []string) []string {
var selected []string
for _, key := range keys {
o[key].AppendOptionsToSlice(&selected)
}
return selected
}
func (m OptionMap) AppendOptionsToSlice(str *[]string) {
for key, values := range m {
for _, value := range values {
// Bool
asBool, ok := value.(bool)
if ok && asBool {
*str = append(*str, optionToString(key))
continue
}
*str = append(*str, optionToString(key), fmt.Sprint(value))
}
}
}
func optionToString(option string) string {
if !strings.HasPrefix(option, "-") {
return "--" + option
}
return option
}

View File

@@ -1,4 +1,4 @@
package utils package internal
import ( import (
"bytes" "bytes"
@@ -9,7 +9,6 @@ import (
"github.com/cupcakearmy/autorestic/internal/colors" "github.com/cupcakearmy/autorestic/internal/colors"
"github.com/cupcakearmy/autorestic/internal/flags" "github.com/cupcakearmy/autorestic/internal/flags"
"github.com/cupcakearmy/autorestic/internal/options"
"github.com/fatih/color" "github.com/fatih/color"
) )
@@ -27,7 +26,6 @@ type ExecuteOptions struct {
Envs map[string]string Envs map[string]string
Dir string Dir string
Silent bool Silent bool
Global options.Options
} }
type ColoredWriter struct { type ColoredWriter struct {
@@ -80,7 +78,8 @@ func ExecuteCommand(options ExecuteOptions, args ...string) (int, string, error)
func ExecuteResticCommand(options ExecuteOptions, args ...string) (int, string, error) { func ExecuteResticCommand(options ExecuteOptions, args ...string) (int, string, error) {
options.Command = flags.RESTIC_BIN options.Command = flags.RESTIC_BIN
var optionsAsString = options.Global.GetOptions([]string{"all"}) var c = GetConfig()
var optionsAsString = getOptions(c.Global, []string{"all"})
args = append(optionsAsString, args...) args = append(optionsAsString, args...)
return ExecuteCommand(options, args...) return ExecuteCommand(options, args...)
} }

View File

@@ -1,3 +0,0 @@
package version
const VERSION = "1.7.7"