diff --git a/Gopkg.lock b/Gopkg.lock index 8b923166b6..5305cc626e 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -844,7 +844,7 @@ branch = "master" name = "yunion.io/x/jsonutils" packages = ["."] - revision = "41e805b221e8fcd9435b706b4dd473df3dd8cff4" + revision = "38477c9cceb895816fe21507d73da30376d358b7" [[projects]] branch = "master" @@ -890,13 +890,13 @@ "util/workqueue", "utils" ] - revision = "56b426f0ca15288cc26442f5802c949f137ade60" + revision = "6c349ecbdb90d5f6ecc9b86596428176c1937b32" [[projects]] branch = "master" name = "yunion.io/x/sqlchemy" packages = ["."] - revision = "a74ef73e555a1ed2e19b1a47e0567814c289eaf9" + revision = "1d049058c031cdc229b0fb92ed902664186657e3" [[projects]] branch = "master" diff --git a/pkg/util/printutils/printjson.go b/pkg/util/printutils/printjson.go index ed01e9ce4e..da14f48590 100644 --- a/pkg/util/printutils/printjson.go +++ b/pkg/util/printutils/printjson.go @@ -58,7 +58,7 @@ func PrintJSONList(list *modules.ListResult, columns []string) { } rows = append(rows, row) } - fmt.Println(pt.GetString(rows)) + fmt.Print(pt.GetString(rows)) title := fmt.Sprintf("Total: %d", list.Total) if list.Limit == 0 && list.Total > len(list.Data) { list.Limit = len(list.Data) @@ -95,7 +95,7 @@ func PrintJSONObject(obj jsonutils.JSONObject) { } rows = append(rows, row) } - fmt.Println(pt.GetString(rows)) + fmt.Print(pt.GetString(rows)) } func PrintJSONBatchResults(results []modules.SubmitResult, columns []string) { diff --git a/vendor/yunion.io/x/jsonutils/unmarshal.go b/vendor/yunion.io/x/jsonutils/unmarshal.go index e1f3b62144..941fcdf729 100644 --- a/vendor/yunion.io/x/jsonutils/unmarshal.go +++ b/vendor/yunion.io/x/jsonutils/unmarshal.go @@ -358,12 +358,12 @@ func (this *JSONArray) unmarshalValue(val reflect.Value) error { val.SetString(this.String()) return nil case reflect.Ptr: - if val.IsNil() { - kind := val.Type().Elem().Kind() - if kind == reflect.Array || kind == reflect.Slice { + kind := val.Type().Elem().Kind() + if kind == reflect.Array || kind == reflect.Slice { + if val.IsNil() { val.Set(reflect.New(val.Type().Elem())) - return this.unmarshalValue(val.Elem()) } + return this.unmarshalValue(val.Elem()) } return fmt.Errorf("JSONArray type mismatch %s", val.Type()) case reflect.Slice, reflect.Array: @@ -373,9 +373,12 @@ func (this *JSONArray) unmarshalValue(val reflect.Value) error { val.Type(), val.Len(), len(this.data)) } } else if val.Kind() == reflect.Slice { - if val.Len() < len(this.data) { - newVal := reflect.MakeSlice(val.Type(), len(this.data), len(this.data)) + dataLen := len(this.data) + if val.Cap() < dataLen { + newVal := reflect.MakeSlice(val.Type(), dataLen, dataLen) val.Set(newVal) + } else if val.Len() != dataLen { + val.SetLen(dataLen) } } for i, json := range this.data { @@ -412,15 +415,15 @@ func (this *JSONDict) unmarshalValue(val reflect.Value) error { case reflect.Struct: return this.unmarshalStruct(val) case reflect.Ptr: - if val.IsNil() { - kind := val.Type().Elem().Kind() - if kind != reflect.Struct && kind != reflect.Map { - return fmt.Errorf("JSONDict type mismatch: %s", val.Type()) + kind := val.Type().Elem().Kind() + if kind == reflect.Struct || kind == reflect.Map { + if val.IsNil() { + newVal := reflect.New(val.Type().Elem()) + val.Set(newVal) } - newVal := reflect.New(val.Type().Elem()) - val.Set(newVal) + return this.unmarshalValue(val.Elem()) } - return this.unmarshalValue(val.Elem()) + fallthrough default: return fmt.Errorf("JSONDict type mismatch: %s", val.Type()) } diff --git a/vendor/yunion.io/x/pkg/gotypes/deepcopy.go b/vendor/yunion.io/x/pkg/gotypes/deepcopy.go new file mode 100644 index 0000000000..f8a186c6d1 --- /dev/null +++ b/vendor/yunion.io/x/pkg/gotypes/deepcopy.go @@ -0,0 +1,100 @@ +package gotypes + +import ( + "reflect" +) + +type DeepCopyFlags uintptr + +func DeepCopy(v interface{}) interface{} { + rv := reflect.ValueOf(v) + cpRv := DeepCopyRv(rv) + cpV := cpRv.Interface() + return cpV +} + +func DeepCopyRv(rv reflect.Value) reflect.Value { + kind := rv.Kind() + if kind == reflect.Invalid { + return reflect.Value{} + } + typ := rv.Type() + switch kind { + case reflect.Ptr: + if rv.IsNil() { + return reflect.New(typ).Elem() + } + elemRv := rv.Elem() + cpElemRv := DeepCopyRv(elemRv) + cpRv := reflect.New(typ.Elem()) + cpRv.Elem().Set(cpElemRv) + return cpRv + case reflect.Slice, reflect.Array: + var cpRv reflect.Value + switch kind { + case reflect.Slice: + if rv.IsNil() { + return reflect.New(typ).Elem() + } + cpRv = reflect.MakeSlice(typ, rv.Len(), rv.Cap()) + case reflect.Array: + cpRv = reflect.New(typ).Elem() + } + n := rv.Len() + for i := 0; i < n; i++ { + elem := rv.Index(i) + cpElem := DeepCopyRv(elem) + cpRvElem := cpRv.Index(i) + cpRvElem.Set(cpElem) + } + return cpRv + case reflect.Struct: + cpRv := reflect.New(typ).Elem() + if typ == TimeType { + cpRv.Set(rv) + } + n := rv.NumField() + for i := 0; i < n; i++ { + f := rv.Field(i) + if f.CanInterface() { + cpRvF := cpRv.Field(i) + cpF := DeepCopyRv(f) + cpRvF.Set(cpF) + } + } + return cpRv + case reflect.Map: + if rv.IsNil() { + return reflect.New(typ).Elem() + } + cpRv := reflect.MakeMap(typ) + mk := rv.MapKeys() + for _, k := range mk { + v := rv.MapIndex(k) + cpK := DeepCopyRv(k) + cpV := DeepCopyRv(v) + cpRv.SetMapIndex(cpK, cpV) + } + return cpRv + case reflect.Interface: + cpRv := reflect.New(typ).Elem() + if !rv.IsNil() { + elemRv := rv.Elem() + cpElemRv := DeepCopyRv(elemRv) + cpRv.Set(cpElemRv) + } + return cpRv + case reflect.Chan: + if rv.IsNil() { + return reflect.New(typ).Elem() + } + return reflect.MakeChan(typ.Elem(), rv.Cap()) + default: + // Invalid, Bool, Int*, Uint*, Float*, Complex*, Func, String + // TODO UnsafePointer + cpRv := reflect.New(typ).Elem() + cpRv.Set(rv) + return cpRv + } + panic("unhandled kind " + kind.String()) +} diff --git a/vendor/yunion.io/x/pkg/prettytable/prettytable.go b/vendor/yunion.io/x/pkg/prettytable/prettytable.go index 8de58e04b0..c0e10aa550 100644 --- a/vendor/yunion.io/x/pkg/prettytable/prettytable.go +++ b/vendor/yunion.io/x/pkg/prettytable/prettytable.go @@ -2,6 +2,7 @@ package prettytable import ( "bytes" + "strings" ) type AlignmentType uint8 @@ -40,6 +41,7 @@ func rowLine(buf *bytes.Buffer, widths []int) { buf.WriteByte('-') buf.WriteByte('+') } + buf.WriteByte('\n') } func textCell(buf *bytes.Buffer, col ptColumn, width int) { @@ -65,13 +67,45 @@ func textCell(buf *bytes.Buffer, col ptColumn, width int) { } func textLine(buf *bytes.Buffer, columns []ptColumn, widths []int) { - buf.WriteByte('|') - for i, w := range widths { - buf.WriteByte(' ') - textCell(buf, columns[i], w) - buf.WriteByte(' ') - buf.WriteByte('|') + nlines := 0 + splitted := make([][]string, len(columns)) + for i, column := range columns { + title := strings.TrimRight(column.Title, "\n") + s := strings.Split(title, "\n") + splitted[i] = s + if nlines < len(s) { + nlines = len(s) + } } + for j := 0; j < nlines; j++ { + buf.WriteByte('|') + for i, w := range widths { + buf.WriteByte(' ') + var text string + if j < len(splitted[i]) { + text = splitted[i][j] + } + c := ptColumn{ + Align: columns[i].Align, + Title: text, + } + textCell(buf, c, w) + buf.WriteByte(' ') + buf.WriteByte('|') + } + buf.WriteByte('\n') + } +} + +func cellWidth(cell string) int { + width := 0 + lines := strings.Split(cell, "\n") + for _, line := range lines { + if width < len(line) { + width = len(line) + } + } + return width } func (this *PrettyTable) GetString(fields [][]string) string { @@ -80,37 +114,32 @@ func (this *PrettyTable) GetString(fields [][]string) string { } var widths = make([]int, len(this.columns)) for i, c := range this.columns { - if widths[i] < len(c.Title) { - widths[i] = len(c.Title) - } + widths[i] = cellWidth(c.Title) } for _, line := range fields { for i, cell := range line { - if widths[i] < len(cell) { - widths[i] = len(cell) + cw := cellWidth(cell) + if widths[i] < cw { + widths[i] = cw } } } var columns = make([]ptColumn, len(this.columns)) var buf bytes.Buffer rowLine(&buf, widths) - buf.WriteByte('\n') for i := 0; i < len(columns); i++ { columns[i].Title = this.columns[i].Title columns[i].Align = AlignCenter } textLine(&buf, columns, widths) - buf.WriteByte('\n') rowLine(&buf, widths) for _, line := range fields { for i := 0; i < len(line); i++ { columns[i].Title = line[i] columns[i].Align = this.columns[i].Align } - buf.WriteByte('\n') textLine(&buf, columns, widths) } - buf.WriteByte('\n') rowLine(&buf, widths) return buf.String() } diff --git a/vendor/yunion.io/x/sqlchemy/update.go b/vendor/yunion.io/x/sqlchemy/update.go index 73cd0b8dfc..d99ef0b95e 100644 --- a/vendor/yunion.io/x/sqlchemy/update.go +++ b/vendor/yunion.io/x/sqlchemy/update.go @@ -7,6 +7,7 @@ import ( "strings" "yunion.io/x/log" + "yunion.io/x/pkg/gotypes" "yunion.io/x/pkg/util/reflectutils" "yunion.io/x/pkg/utils" ) @@ -20,7 +21,6 @@ func (ts *STableSpec) prepareUpdate(dt interface{}) (*SUpdateSession, error) { if reflect.ValueOf(dt).Kind() != reflect.Ptr { return nil, fmt.Errorf("Update input must be a Pointer") } - dataType := reflect.TypeOf(dt).Elem() dataValue := reflect.ValueOf(dt).Elem() fields := reflectutils.FetchStructFieldNameValueInterfaces(dataValue) // fetchStructFieldNameValue(dataType, dataValue) @@ -41,8 +41,7 @@ func (ts *STableSpec) prepareUpdate(dt interface{}) (*SUpdateSession, error) { strings.Join(zeroPrimary, ","), strings.Join(zeroKeyIndex, ",")) } - originValue := reflect.Indirect(reflect.New(dataType)) - originValue.Set(dataValue) + originValue := gotypes.DeepCopyRv(dataValue) us := SUpdateSession{oValue: originValue, tableSpec: ts} return &us, nil }