forked from TrueCloudLab/restic
wip
This commit is contained in:
parent
e4c0d77bdd
commit
722517c480
6 changed files with 183 additions and 0 deletions
76
internal/ui/config/config.go
Normal file
76
internal/ui/config/config.go
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/hashicorp/hcl"
|
||||||
|
"github.com/hashicorp/hcl/hcl/ast"
|
||||||
|
"github.com/hashicorp/hcl/hcl/token"
|
||||||
|
"github.com/restic/restic/internal/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Repo is a configured repository
|
||||||
|
type Repo struct {
|
||||||
|
Backend string
|
||||||
|
Path string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config contains configuration items read from a file.
|
||||||
|
type Config struct {
|
||||||
|
Quiet bool `hcl:"quiet"`
|
||||||
|
Repos map[string]Repo `hcl:"repo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// listTags returns the all the top-level tags with the name tagname of obj.
|
||||||
|
func listTags(obj interface{}, tagname string) map[string]struct{} {
|
||||||
|
list := make(map[string]struct{})
|
||||||
|
|
||||||
|
// resolve indirection if obj is a pointer
|
||||||
|
v := reflect.Indirect(reflect.ValueOf(obj))
|
||||||
|
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
f := v.Type().Field(i)
|
||||||
|
|
||||||
|
val := f.Tag.Get(tagname)
|
||||||
|
list[val] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parses a config file from buf.
|
||||||
|
func Parse(buf []byte) (cfg Config, err error) {
|
||||||
|
parsed, err := hcl.ParseBytes(buf)
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = hcl.DecodeObject(&cfg, parsed)
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for additional top-level items
|
||||||
|
validNames := listTags(cfg, "hcl")
|
||||||
|
for _, item := range parsed.Node.(*ast.ObjectList).Items {
|
||||||
|
fmt.Printf("-----------\n")
|
||||||
|
spew.Dump(item)
|
||||||
|
var ident string
|
||||||
|
for _, key := range item.Keys {
|
||||||
|
if key.Token.Type == token.IDENT {
|
||||||
|
ident = key.Token.Text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Printf("ident is %q\n", ident)
|
||||||
|
|
||||||
|
if _, ok := validNames[ident]; !ok {
|
||||||
|
return Config{}, errors.Errorf("unknown option %q found at line %v, column %v: %v",
|
||||||
|
ident, item.Pos().Line, item.Pos().Column)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// spew.Dump(cfg)
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
83
internal/ui/config/config_test.go
Normal file
83
internal/ui/config/config_test.go
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"io/ioutil"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
)
|
||||||
|
|
||||||
|
var updateGoldenFiles = flag.Bool("update", false, "update golden files in testdata/")
|
||||||
|
|
||||||
|
func readTestFile(t testing.TB, filename string) []byte {
|
||||||
|
data, err := ioutil.ReadFile(filepath.Join("testdata", filename))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func saveGoldenFile(t testing.TB, base string, cfg Config) {
|
||||||
|
buf, err := json.MarshalIndent(cfg, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error marshaling result: %v", err)
|
||||||
|
}
|
||||||
|
buf = append(buf, '\n')
|
||||||
|
|
||||||
|
if err = ioutil.WriteFile(filepath.Join("testdata", base+".golden"), buf, 0644); err != nil {
|
||||||
|
t.Fatalf("unable to update golden file: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadGoldenFile(t testing.TB, base string) Config {
|
||||||
|
buf, err := ioutil.ReadFile(filepath.Join("testdata", base+".golden"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfg Config
|
||||||
|
err = json.Unmarshal(buf, &cfg)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRead(t *testing.T) {
|
||||||
|
entries, err := ioutil.ReadDir("testdata")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entry := range entries {
|
||||||
|
filename := entry.Name()
|
||||||
|
if filepath.Ext(filename) != ".conf" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
base := strings.TrimSuffix(filename, ".conf")
|
||||||
|
t.Run(base, func(t *testing.T) {
|
||||||
|
buf := readTestFile(t, filename)
|
||||||
|
|
||||||
|
cfg, err := Parse(buf)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *updateGoldenFiles {
|
||||||
|
saveGoldenFile(t, base, cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
want := loadGoldenFile(t, base)
|
||||||
|
|
||||||
|
if !cmp.Equal(want, cfg) {
|
||||||
|
t.Errorf("wrong config: %v", cmp.Diff(want, cfg))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
1
internal/ui/config/testdata/quiet.conf
vendored
Normal file
1
internal/ui/config/testdata/quiet.conf
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
quiet = true
|
4
internal/ui/config/testdata/quiet.golden
vendored
Normal file
4
internal/ui/config/testdata/quiet.golden
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"Quiet": true,
|
||||||
|
"Repos": null
|
||||||
|
}
|
10
internal/ui/config/testdata/repo_local.conf
vendored
Normal file
10
internal/ui/config/testdata/repo_local.conf
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
repo "test" {
|
||||||
|
backend = "local"
|
||||||
|
path = "/foo/bar/baz"
|
||||||
|
}
|
||||||
|
|
||||||
|
foobar "test" {
|
||||||
|
x = "y"
|
||||||
|
}
|
||||||
|
|
||||||
|
quiet = false
|
9
internal/ui/config/testdata/repo_local.golden
vendored
Normal file
9
internal/ui/config/testdata/repo_local.golden
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"Quiet": false,
|
||||||
|
"Repos": {
|
||||||
|
"test": {
|
||||||
|
"Backend": "local",
|
||||||
|
"Path": "/foo/bar/baz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue