diff --git a/base/nfs/cat.go b/base/nfs/cat.go index 1cb7423f..69ae02d0 100644 --- a/base/nfs/cat.go +++ b/base/nfs/cat.go @@ -54,7 +54,7 @@ func _cat_show(m *ice.Message, name string) { } // 打包文件 - if b, ok := ice.BinPack[name]; ok { + if b, ok := ice.Info.BinPack[name]; ok { m.Logs("binpack", name, kit.MDB_SIZE, len(b)) m.Echo(string(b)) return diff --git a/base/ssh/scripts.go b/base/ssh/scripts.go index 1120c9d7..749ca360 100644 --- a/base/ssh/scripts.go +++ b/base/ssh/scripts.go @@ -73,7 +73,7 @@ func Script(m *ice.Message, name string) io.Reader { } // 打包文件 - if b, ok := ice.BinPack["/"+name]; ok { + if b, ok := ice.Info.BinPack["/"+name]; ok { m.Info("binpack %v %v", len(b), name) return bytes.NewReader(b) } diff --git a/base/web/render.go b/base/web/render.go index 390780c9..7badd1db 100644 --- a/base/web/render.go +++ b/base/web/render.go @@ -41,7 +41,7 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) { case ice.RENDER_DOWNLOAD: // file [type [name]] msg.W.Header().Set("Content-Disposition", fmt.Sprintf("filename=%s", kit.Select(path.Base(arg[0]), arg, 2))) - if RenderType(msg.W, arg[0], kit.Select("", arg, 1)); !ice.DumpBinPack(msg.W, arg[0], nil) { + if RenderType(msg.W, arg[0], kit.Select("", arg, 1)); !ice.Dump(msg.W, arg[0], nil) { http.ServeFile(msg.W, msg.R, kit.Path(arg[0])) } diff --git a/base/web/serve.go b/base/web/serve.go index 4f4ba24e..16b2350b 100644 --- a/base/web/serve.go +++ b/base/web/serve.go @@ -65,7 +65,7 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool { } // 文件接口 - if ice.DumpBinPack(w, r.URL.Path, func(name string) { RenderType(w, name, "") }) { + if ice.Dump(w, r.URL.Path, func(name string) { RenderType(w, name, "") }) { return false } return true diff --git a/conf.go b/conf.go index 2fde5935..0e93d6a7 100644 --- a/conf.go +++ b/conf.go @@ -19,19 +19,21 @@ const ( // REPOS INTSHELL = "intshell" CONTEXTS = "contexts" - PUBLISH = "publish" + INSTALL = "install" REQUIRE = "require" + PUBLISH = "publish" SUCCESS = "success" FAILURE = "failure" TRUE = "true" + OK = "ok" ) const ( // DIR USR_VOLCANOS = "usr/volcanos" USR_ICEBERGS = "usr/icebergs" USR_INTSHELL = "usr/intshell" - USR_PUBLISH = "usr/publish" USR_INSTALL = "usr/install" + USR_PUBLISH = "usr/publish" USR_LOCAL = "usr/local" PROTO_JS = "proto.js" @@ -64,9 +66,10 @@ const ( // DIR GO_MOD = "go.mod" GO_SUM = "go.sum" - CTX_DEV = "ctx_dev" - CTX_PID = "ctx_pid" - CTX_LOG = "ctx_log" + CTX_DEBUG = "ctx_debug" + CTX_DEV = "ctx_dev" + CTX_PID = "ctx_pid" + CTX_LOG = "ctx_log" ) const ( // MSG MSG_DETAIL = "detail" diff --git a/core/code/binpack.go b/core/code/binpack.go index 92036181..46fe7584 100644 --- a/core/code/binpack.go +++ b/core/code/binpack.go @@ -108,7 +108,7 @@ func init() { } }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - for k, v := range ice.BinPack { + for k, v := range ice.Info.BinPack { m.Push(kit.MDB_NAME, k) m.Push(kit.MDB_SIZE, len(v)) } diff --git a/init.go b/init.go index f9ec7a29..ab78f993 100644 --- a/init.go +++ b/init.go @@ -1,42 +1,19 @@ package ice import ( - "fmt" "io" "os" "strings" "sync" - "sync/atomic" "time" kit "github.com/shylinux/toolkits" ) -var Info = struct { - HostName string - PathName string - UserName string - PassWord string - - NodeType string - NodeName string - CtxShare string - CtxRiver string - - Make struct { - Time string - Hash string - Remote string - Branch string - Version string - HostName string - UserName string - } - - nLocalCmd int32 -}{} - -type Frame struct{ code int } +type Frame struct { + code int + wait chan bool +} func (f *Frame) Spawn(m *Message, c *Context, arg ...string) Server { return &Frame{} @@ -131,7 +108,7 @@ var Index = &Context{Name: "ice", Help: "冰山模块", }}, }, Hand: func(m *Message, c *Context, cmd string, arg ...string) { m.root.target.server.(*Frame).code = kit.Int(kit.Select("0", arg, 0)) - m.Cmd("ssh.source", "etc/exit.shy", "exit.shy", "退出配置") + m.Cmd("ssh.source", ETC_EXIT, "exit.shy", "退出配置") m.root.Cmd(CTX_EXIT) }}, CTX_EXIT: {Hand: func(m *Message, c *Context, cmd string, arg ...string) { @@ -143,7 +120,8 @@ var Index = &Context{Name: "ice", Help: "冰山模块", }) } }) - wait <- true + f := c.server.(*Frame) + f.wait <- true }}, }, } @@ -154,8 +132,64 @@ var Pulse = &Message{ source: Index, target: Index, Hand: true, } -var wait = make(chan bool, 1) +var Info = struct { + HostName string + PathName string + UserName string + PassWord string + NodeType string + NodeName string + CtxShare string + CtxRiver string + + Make struct { + Time string + Hash string + Remote string + Branch string + Version string + HostName string + UserName string + } + + BinPack map[string][]byte + names map[string]interface{} +}{ + BinPack: map[string][]byte{}, + names: map[string]interface{}{}, +} + +func Dump(w io.Writer, name string, cb func(string)) bool { + if b, ok := Info.BinPack[name]; ok { + if cb != nil { + cb(name) + } + w.Write(b) + return true + } + if b, ok := Info.BinPack[strings.TrimPrefix(name, USR_VOLCANOS)]; ok { + if cb != nil { + cb(name) + } + w.Write(b) + return true + } + return false +} +func Name(name string, value interface{}) string { + if s, ok := Info.names[name]; ok { + last := "" + switch s := s.(type) { + case *Context: + last = s.Name + } + panic(kit.Format("%s %s %v", ErrExists, name, last)) + } + + Info.names[name] = value + return name +} func Run(arg ...string) string { if len(arg) == 0 { arg = os.Args[1:] @@ -164,7 +198,7 @@ func Run(arg ...string) string { arg = append(arg, "help") } - frame := &Frame{} + frame := &Frame{wait: make(chan bool, 1)} Index.root = Index Index.server = frame Index.Merge(Index) @@ -179,11 +213,11 @@ func Run(arg ...string) string { frame.Close(Pulse.Spawn(), arg...) } - <-wait + <-frame.wait os.Exit(frame.code) default: - _log_disable = os.Getenv("ctx_debug") != "true" + _log_disable = os.Getenv(CTX_DEBUG) != TRUE if Pulse.Cmdy(arg); Pulse.Result() == "" { Pulse.Table() } @@ -195,45 +229,3 @@ func Run(arg ...string) string { return Pulse.Result() } - -var BinPack = map[string][]byte{} - -func DumpBinPack(w io.Writer, name string, cb func(string)) bool { - if b, ok := BinPack[name]; ok { - if cb != nil { - cb(name) - } - w.Write(b) - return true - } - if b, ok := BinPack[strings.TrimPrefix(name, "usr/volcanos")]; ok { - if cb != nil { - cb(name) - } - w.Write(b) - return true - } - return false -} - -var names = map[string]interface{}{} -var ErrNameExists = "name already exists: " - -func Name(name string, value interface{}) string { - if s, ok := names[name]; ok { - last := "" - switch s := s.(type) { - case *Context: - last = s.Name - } - panic(kit.Format("name already exits: %s %v", name, last)) - } - - names[name] = value - return name -} -func (m *Message) AddCmd(cmd *Command) string { - name := fmt.Sprintf("_cb_%d", atomic.AddInt32(&Info.nLocalCmd, 1)) - m.target.Commands[name] = cmd - return kit.Keys(m.target.Cap(CTX_FOLLOW), name) -} diff --git a/logs.go b/logs.go index 58846001..9e1072cb 100644 --- a/logs.go +++ b/logs.go @@ -8,13 +8,14 @@ import ( log "github.com/shylinux/toolkits/logs" ) -var OK = "ok" -var ErrWarn = "warn: " -var ErrExpire = "expire: " -var ErrNotLogin = "not login: " -var ErrNotRight = "not right: " -var ErrNotFound = "not found: " -var ErrNotShare = "not share: " +const ( + ErrWarn = "warn: " + ErrExists = "exists: " + ErrExpire = "expire: " + ErrNotLogin = "not login: " + ErrNotFound = "not found: " + ErrNotRight = "not right: " +) var _log_disable = true var Log func(m *Message, p, l, s string) diff --git a/meta.go b/meta.go index b9bfa4fc..09bb3791 100644 --- a/meta.go +++ b/meta.go @@ -1,8 +1,6 @@ package ice import ( - "bytes" - "encoding/csv" "fmt" "sort" "strconv" @@ -345,104 +343,6 @@ func (m *Message) Table(cbs ...func(index int, value map[string]string, head []s } return m } -func (m *Message) Render(cmd string, args ...interface{}) *Message { - m.Optionv(MSG_OUTPUT, cmd) - m.Optionv(MSG_ARGS, args) - - switch cmd { - case RENDER_TEMPLATE: // text [data [type]] - if len(args) == 1 { - args = append(args, m) - } - if res, err := kit.Render(args[0].(string), args[1]); m.Assert(err) { - m.Echo(string(res)) - } - } - return m -} -func (m *Message) Parse(meta string, key string, arg ...string) *Message { - list := []string{} - for _, line := range kit.Split(strings.Join(arg, " "), "\n") { - ls := kit.Split(line) - for i := 0; i < len(ls); i++ { - if strings.HasPrefix(ls[i], "#") { - ls = ls[:i] - break - } - } - list = append(list, ls...) - } - - switch data := kit.Parse(nil, "", list...); meta { - case MSG_OPTION: - m.Option(key, data) - case MSG_APPEND: - m.Append(key, data) - } - return m -} -func (m *Message) Split(str string, field string, space string, enter string) *Message { - indexs := []int{} - fields := kit.Split(field, space, space, space) - for i, l := range kit.Split(str, enter, enter, enter) { - if strings.HasPrefix(l, "Binary") { - continue - } - if strings.TrimSpace(l) == "" { - continue - } - if i == 0 && (field == "" || field == "index") { - // 表头行 - fields = kit.Split(l, space, space) - if field == "index" { - for _, v := range fields { - indexs = append(indexs, strings.Index(l, v)) - } - } - continue - } - - if len(indexs) > 0 { - // 数据行 - for i, v := range indexs { - if i == len(indexs)-1 { - m.Push(kit.Select("some", fields, i), l[v:]) - } else { - m.Push(kit.Select("some", fields, i), l[v:indexs[i+1]]) - } - } - continue - } - - ls := kit.Split(l, space, space) - for i, v := range ls { - if i == len(fields)-1 { - m.Push(kit.Select("some", fields, i), strings.Join(ls[i:], space)) - break - } - m.Push(kit.Select("some", fields, i), v) - } - } - return m -} -func (m *Message) CSV(text string, head ...string) *Message { - bio := bytes.NewBufferString(text) - r := csv.NewReader(bio) - - if len(head) == 0 { - head, _ = r.Read() - } - for { - line, e := r.Read() - if e != nil { - break - } - for i, k := range head { - m.Push(k, kit.Select("", line, i)) - } - } - return m -} func (m *Message) Detail(arg ...interface{}) string { return kit.Select("", m.meta[MSG_DETAIL], 0) diff --git a/misc.go b/misc.go index b8d9fb74..c87cdf37 100644 --- a/misc.go +++ b/misc.go @@ -1,6 +1,8 @@ package ice import ( + "bytes" + "encoding/csv" "encoding/json" "fmt" "net/url" @@ -115,13 +117,6 @@ func (m *Message) PushSearchWeb(cmd string, name string) { }) } -func (m *Message) IsCliUA() bool { - if m.Option(MSG_USERUA) == "" || !strings.HasPrefix(m.Option(MSG_USERUA), "Mozilla/5.0") { - return true - } - return false -} - func Render(m *Message, cmd string, args ...interface{}) string { if m.IsCliUA() { switch arg := kit.Simple(args...); cmd { @@ -252,27 +247,62 @@ func (m *Message) SortTimeR(key string) { m.Sort(key, "time_r") } func (m *Message) FormatMeta() string { return m.Format("meta") } func (m *Message) FormatSize() string { return m.Format("size") } func (m *Message) FormatCost() string { return m.Format("cost") } -func (m *Message) RenameAppend(from, to string) { - for i, v := range m.meta[MSG_APPEND] { - if v == from { - m.meta[MSG_APPEND][i] = to - m.meta[to] = m.meta[from] - delete(m.meta, from) - } - } -} +type Sort struct { + Fields string + Method string +} type Option struct { Name string Value interface{} } -func OptionFields(str string) Option { return Option{MSG_FIELDS, str} } -func OptionHash(str string) Option { return Option{kit.MDB_HASH, str} } +func OptionFields(str string) Option { return Option{MSG_FIELDS, str} } +func OptionHash(str string) Option { return Option{kit.MDB_HASH, str} } +func (m *Message) OptionFields(str string) { m.Option(MSG_FIELDS, str) } +func (m *Message) OptionLoad(file string) *Message { + if f, e := os.Open(file); e == nil { + defer f.Close() -type Sort struct { - Fields string - Method string + var data interface{} + json.NewDecoder(f).Decode(&data) + + kit.Fetch(data, func(key string, value interface{}) { m.Option(key, kit.Simple(value)) }) + } + return m +} +func (m *Message) Fields(condition bool, fields string) string { + return m.Option(MSG_FIELDS, kit.Select(kit.Select("detail", fields, condition), m.Option(MSG_FIELDS))) +} +func (m *Message) Upload(dir string) { + up := kit.Simple(m.Optionv(MSG_UPLOAD)) + if p := path.Join(dir, up[1]); m.Option(MSG_USERPOD) == "" { + // 本机文件 + m.Cmdy("web.cache", "watch", up[0], p) + } else { + // 下拉文件 + m.Cmdy("web.spide", "dev", "save", p, "GET", + kit.MergeURL2(m.Option(MSG_USERWEB), path.Join("/share/cache", up[0]))) + } +} +func (m *Message) Action(arg ...string) { + m.Option(MSG_ACTION, kit.Format(arg)) +} +func (m *Message) Status(arg ...interface{}) { + args := kit.Simple(arg) + list := []map[string]string{} + for i := 0; i < len(args)-1; i += 2 { + list = append(list, map[string]string{ + "name": args[i], "value": args[i+1], + }) + } + m.Option(MSG_STATUS, kit.Format(list)) +} +func (m *Message) StatusTimeCount(arg ...interface{}) { + m.Status(kit.MDB_TIME, m.Time(), kit.MDB_COUNT, m.FormatSize(), arg, "cost", m.FormatCost()) +} +func (m *Message) StatusTimeCountTotal(arg ...interface{}) { + m.Status(kit.MDB_TIME, m.Time(), kit.MDB_COUNT, m.FormatSize(), "total", arg, "cost", m.FormatCost()) } func (m *Message) Toast(content string, arg ...interface{}) { @@ -303,31 +333,6 @@ func (m *Message) GoToast(title string, cb func(toast func(string, int, int))) { }) }) } - -func (m *Message) Fields(condition bool, fields string) string { - return m.Option(MSG_FIELDS, kit.Select(kit.Select("detail", fields, condition), m.Option(MSG_FIELDS))) -} -func (m *Message) Action(arg ...string) { - m.Option(MSG_ACTION, kit.Format(arg)) -} -func (m *Message) Status(arg ...interface{}) { - args := kit.Simple(arg) - list := []map[string]string{} - for i := 0; i < len(args)-1; i += 2 { - list = append(list, map[string]string{ - "name": args[i], "value": args[i+1], - }) - } - m.Option(MSG_STATUS, kit.Format(list)) -} - -func (m *Message) StatusTimeCount(arg ...interface{}) { - m.Status(kit.MDB_TIME, m.Time(), kit.MDB_COUNT, m.FormatSize(), arg, "cost", m.FormatCost()) -} -func (m *Message) StatusTimeCountTotal(arg ...interface{}) { - m.Status(kit.MDB_TIME, m.Time(), kit.MDB_COUNT, m.FormatSize(), "total", arg, "cost", m.FormatCost()) -} - func (m *Message) Process(action string, arg ...interface{}) { m.Option(MSG_PROCESS, action) m.Option("_arg", arg...) @@ -353,31 +358,6 @@ func (m *Message) ProcessInner() { m.Process(PROCESS_INNER) } func (m *Message) ProcessHold() { m.Process(PROCESS_HOLD) } func (m *Message) ProcessBack() { m.Process(PROCESS_BACK) } -func (m *Message) Upload(dir string) { - up := kit.Simple(m.Optionv(MSG_UPLOAD)) - if p := path.Join(dir, up[1]); m.Option(MSG_USERPOD) == "" { - // 本机文件 - m.Cmdy("web.cache", "watch", up[0], p) - } else { - // 下拉文件 - m.Cmdy("web.spide", "dev", "save", p, "GET", - kit.MergeURL2(m.Option(MSG_USERWEB), path.Join("/share/cache", up[0]))) - } -} - -func (m *Message) OptionFields(str string) { m.Option(MSG_FIELDS, str) } -func (m *Message) OptionLoad(file string) *Message { - if f, e := os.Open(file); e == nil { - defer f.Close() - - var data interface{} - json.NewDecoder(f).Decode(&data) - - kit.Fetch(data, func(key string, value interface{}) { m.Option(key, kit.Simple(value)) }) - } - return m -} - func (m *Message) Confi(key string, sub string) int { return kit.Int(m.Conf(key, sub)) } @@ -391,3 +371,116 @@ func (m *Message) Cut(fields ...string) *Message { m.meta[MSG_APPEND] = strings.Split(strings.Join(fields, ","), ",") return m } +func (m *Message) Render(cmd string, args ...interface{}) *Message { + m.Optionv(MSG_OUTPUT, cmd) + m.Optionv(MSG_ARGS, args) + + switch cmd { + case RENDER_TEMPLATE: // text [data [type]] + if len(args) == 1 { + args = append(args, m) + } + if res, err := kit.Render(args[0].(string), args[1]); m.Assert(err) { + m.Echo(string(res)) + } + } + return m +} +func (m *Message) Parse(meta string, key string, arg ...string) *Message { + list := []string{} + for _, line := range kit.Split(strings.Join(arg, " "), "\n") { + ls := kit.Split(line) + for i := 0; i < len(ls); i++ { + if strings.HasPrefix(ls[i], "#") { + ls = ls[:i] + break + } + } + list = append(list, ls...) + } + + switch data := kit.Parse(nil, "", list...); meta { + case MSG_OPTION: + m.Option(key, data) + case MSG_APPEND: + m.Append(key, data) + } + return m +} +func (m *Message) Split(str string, field string, space string, enter string) *Message { + indexs := []int{} + fields := kit.Split(field, space, space, space) + for i, l := range kit.Split(str, enter, enter, enter) { + if strings.HasPrefix(l, "Binary") { + continue + } + if strings.TrimSpace(l) == "" { + continue + } + if i == 0 && (field == "" || field == "index") { + // 表头行 + fields = kit.Split(l, space, space) + if field == "index" { + for _, v := range fields { + indexs = append(indexs, strings.Index(l, v)) + } + } + continue + } + + if len(indexs) > 0 { + // 数据行 + for i, v := range indexs { + if i == len(indexs)-1 { + m.Push(kit.Select("some", fields, i), l[v:]) + } else { + m.Push(kit.Select("some", fields, i), l[v:indexs[i+1]]) + } + } + continue + } + + ls := kit.Split(l, space, space) + for i, v := range ls { + if i == len(fields)-1 { + m.Push(kit.Select("some", fields, i), strings.Join(ls[i:], space)) + break + } + m.Push(kit.Select("some", fields, i), v) + } + } + return m +} +func (m *Message) CSV(text string, head ...string) *Message { + bio := bytes.NewBufferString(text) + r := csv.NewReader(bio) + + if len(head) == 0 { + head, _ = r.Read() + } + for { + line, e := r.Read() + if e != nil { + break + } + for i, k := range head { + m.Push(k, kit.Select("", line, i)) + } + } + return m +} +func (m *Message) RenameAppend(from, to string) { + for i, v := range m.meta[MSG_APPEND] { + if v == from { + m.meta[MSG_APPEND][i] = to + m.meta[to] = m.meta[from] + delete(m.meta, from) + } + } +} +func (m *Message) IsCliUA() bool { + if m.Option(MSG_USERUA) == "" || !strings.HasPrefix(m.Option(MSG_USERUA), "Mozilla/5.0") { + return true + } + return false +} diff --git a/type.go b/type.go index f54a7f4f..17cfd961 100644 --- a/type.go +++ b/type.go @@ -79,7 +79,7 @@ func (c *Context) Cap(key string, arg ...interface{}) string { } return c.Caches[key].Value } -func (c *Context) _hand(m *Message, cmd *Command, key string, k string, h *Action, arg ...string) *Message { +func (c *Context) _cmd(m *Message, cmd *Command, key string, k string, h *Action, arg ...string) *Message { m.Log(LOG_CMDS, "%s.%s %s %d %v %s", c.Name, key, k, len(arg), arg, kit.FileLine(h.Hand, 3)) if len(h.List) > 0 && k != "search" { order := false @@ -118,12 +118,12 @@ func (c *Context) cmd(m *Message, cmd *Command, key string, arg ...string) *Mess m.meta[MSG_DETAIL] = kit.Simple(key, arg) if m.Hand = true; len(arg) > 1 && arg[0] == kit.MDB_ACTION && cmd.Action != nil { if h, ok := cmd.Action[arg[1]]; ok { - return c._hand(m, cmd, key, arg[1], h, arg[2:]...) + return c._cmd(m, cmd, key, arg[1], h, arg[2:]...) } } if len(arg) > 0 && arg[0] != "command" && cmd.Action != nil { if h, ok := cmd.Action[arg[0]]; ok { - return c._hand(m, cmd, key, arg[0], h, arg[1:]...) + return c._cmd(m, cmd, key, arg[0], h, arg[1:]...) } } @@ -182,7 +182,7 @@ func (c *Context) Merge(s *Context) *Context { c.Commands[k] = v if v.List == nil { - v.List = c._split(k, v, v.Name) + v.List = c.split(k, v, v.Name) } if v.Meta == nil { v.Meta = kit.Dict() @@ -203,7 +203,7 @@ func (c *Context) Merge(s *Context) *Context { continue } if a.List == nil { - a.List = c._split(k, nil, a.Name) + a.List = c.split(k, nil, a.Name) } if len(a.List) > 0 { v.Meta[k] = a.List @@ -226,7 +226,7 @@ func (c *Context) Merge(s *Context) *Context { } return c } -func (c *Context) _split(key string, cmd *Command, name string) []interface{} { +func (c *Context) split(key string, cmd *Command, name string) []interface{} { button, list := false, []interface{}{} for _, v := range kit.Split(kit.Select("key", name), " ", " ")[1:] { switch v { @@ -580,7 +580,7 @@ func (m *Message) Search(key string, cb interface{}) *Message { // 查找模块 p := m.target.root - if ctx, ok := names[key].(*Context); ok { + if ctx, ok := Info.names[key].(*Context); ok { p = ctx } else if key == "ice." { p, key = m.target.root, ""