config: Do not migrate config file if not needed. (#4264)

Also improve the error message returned by `pkg/quick`.

Fixes #4233
This commit is contained in:
Harshavardhana
2017-05-06 10:16:59 -07:00
committed by GitHub
parent 2df1e2e9a9
commit 610dbe3479
7 changed files with 214 additions and 91 deletions

View File

@@ -21,6 +21,7 @@ package quick
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"path/filepath"
"runtime"
@@ -55,12 +56,15 @@ func (j jsonEncoding) Unmarshal(b []byte, v interface{}) error {
err := json.Unmarshal(b, v)
if err != nil {
// Try to return a sophisticated json error message if possible
switch err := err.(type) {
switch jerr := err.(type) {
case *json.SyntaxError:
return FormatJSONSyntaxError(bytes.NewReader(b), err)
default:
return err
return fmt.Errorf("Unable to parse JSON schema due to a syntax error at '%s'",
FormatJSONSyntaxError(bytes.NewReader(b), jerr.Offset))
case *json.UnmarshalTypeError:
return fmt.Errorf("Unable to parse JSON, type '%v' cannot be converted into the Go '%v' type",
jerr.Value, jerr.Type)
}
return err
}
return nil
}

View File

@@ -21,28 +21,22 @@ package quick
import (
"bufio"
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"github.com/cheggaaa/pb"
)
const errorFmt = "%5d: %s <-- "
const errorFmt = "%5d: %s <<<<"
// FormatJSONSyntaxError generates a pretty printed json syntax error since
// golang doesn't provide an easy way to report the location of the error
func FormatJSONSyntaxError(data io.Reader, sErr *json.SyntaxError) error {
if sErr == nil {
return nil
}
func FormatJSONSyntaxError(data io.Reader, offset int64) (highlight string) {
var readLine bytes.Buffer
var errLine = 1
var readBytes int64
bio := bufio.NewReader(data)
errLine := int64(1)
readBytes := int64(0)
// termWidth is set to a default one to use when we are
// not able to calculate terminal width via OS syscalls
@@ -60,13 +54,10 @@ func FormatJSONSyntaxError(data io.Reader, sErr *json.SyntaxError) error {
for {
b, err := bio.ReadByte()
if err != nil {
if err != io.EOF {
return err
}
break
}
readBytes++
if readBytes > sErr.Offset {
if readBytes > offset {
break
}
switch b {
@@ -88,9 +79,5 @@ func FormatJSONSyntaxError(data io.Reader, sErr *json.SyntaxError) error {
idx = 0
}
errorStr := fmt.Sprintf("JSON syntax error at line %d, col %d : %s.\n",
errLine, readLine.Len(), sErr)
errorStr += fmt.Sprintf(errorFmt, errLine, readLine.String()[idx:])
return errors.New(errorStr)
return fmt.Sprintf(errorFmt, errLine, readLine.String()[idx:])
}

View File

@@ -127,7 +127,7 @@ func (d config) Diff(c Config) ([]structs.Field, error) {
return fields, nil
}
//DeepDiff - list fields in A that are missing or not equal to fields in B
// DeepDiff - list fields in A that are missing or not equal to fields in B
func (d config) DeepDiff(c Config) ([]structs.Field, error) {
var fields []structs.Field
@@ -196,12 +196,22 @@ func New(data interface{}) (Config, error) {
return d, nil
}
// GetVersion - extracts the version information.
func GetVersion(filename string) (version string, err error) {
var qc Config
if qc, err = Load(filename, &struct {
Version string
}{}); err != nil {
return "", err
}
return qc.Version(), err
}
// Load - loads json config from filename for the a given struct data
func Load(filename string, data interface{}) (qc Config, err error) {
if qc, err = New(data); err == nil {
err = qc.Load(filename)
}
return qc, err
}

View File

@@ -36,6 +36,42 @@ type MySuite struct{}
var _ = Suite(&MySuite{})
func (s *MySuite) TestReadVersion(c *C) {
type myStruct struct {
Version string
}
saveMe := myStruct{"1"}
config, err := New(&saveMe)
c.Assert(err, IsNil)
err = config.Save("test.json")
c.Assert(err, IsNil)
version, err := GetVersion("test.json")
c.Assert(err, IsNil)
c.Assert(version, Equals, "1")
}
func (s *MySuite) TestReadVersionErr(c *C) {
type myStruct struct {
Version int
}
saveMe := myStruct{1}
_, err := New(&saveMe)
c.Assert(err, Not(IsNil))
err = ioutil.WriteFile("test.json", []byte("{ \"version\":2,"), 0644)
c.Assert(err, IsNil)
_, err = GetVersion("test.json")
c.Assert(err, Not(IsNil))
err = ioutil.WriteFile("test.json", []byte("{ \"version\":2 }"), 0644)
c.Assert(err, IsNil)
_, err = GetVersion("test.json")
c.Assert(err, Not(IsNil))
}
func (s *MySuite) TestSaveFailOnDir(c *C) {
defer os.RemoveAll("test.json")
e := os.MkdirAll("test.json", 0644)