diff --git a/base/base.shy b/base/base.shy
new file mode 100644
index 00000000..ed35653e
--- /dev/null
+++ b/base/base.shy
@@ -0,0 +1,5 @@
+label `
+ctx mdb web aaa
+lex yac ssh gdb
+tcp nfs cli log
+`
\ No newline at end of file
diff --git a/base/cli/system.go b/base/cli/system.go
index 537ed8f3..03b0a8ab 100644
--- a/base/cli/system.go
+++ b/base/cli/system.go
@@ -165,7 +165,7 @@ func init() {
mdb.HashSelect(m)
return
}
- mdb.HashCreate(m.Spawn(), ice.CMD, arg[0], ice.ARG, kit.Join(arg[1:], ice.SP))
+ // mdb.HashCreate(m.Spawn(), ice.CMD, arg[0], ice.ARG, kit.Join(arg[1:], ice.SP))
if _system_exec(m, _system_cmd(m, kit.Simple(kit.Split(arg[0]), arg[1:])...)); IsSuccess(m) && m.Append(CMD_ERR) == "" {
m.SetAppend()
}
diff --git a/base/ctx/display.go b/base/ctx/display.go
index 2712aea5..a14fb231 100644
--- a/base/ctx/display.go
+++ b/base/ctx/display.go
@@ -27,6 +27,9 @@ func DisplayTableCard(m *ice.Message, arg ...ice.Any) *ice.Message {
return DisplayTable(m, "style", "card")
}
func DisplayStory(m *ice.Message, file string, arg ...ice.Any) *ice.Message {
+ if file == "" {
+ file = kit.ExtChange(kit.FileName(2), nfs.JS)
+ }
if !strings.HasPrefix(file, ice.PS) && !strings.HasPrefix(file, ice.HTTP) {
file = path.Join(ice.PLUGIN_STORY, file)
}
diff --git a/base/mdb/mdb.go b/base/mdb/mdb.go
index 16395e9a..0cb9594f 100644
--- a/base/mdb/mdb.go
+++ b/base/mdb/mdb.go
@@ -3,6 +3,7 @@ package mdb
import (
"path"
"strings"
+ "sync"
ice "shylinux.com/x/icebergs"
kit "shylinux.com/x/toolkits"
@@ -303,3 +304,20 @@ func Config(m *ice.Message, key string, arg ...ice.Any) string {
}
return m.Config(key, arg...)
}
+
+var cache = sync.Map{}
+
+func Cache(m *ice.Message, key string, add func() ice.Any) ice.Any {
+ if add == nil {
+ cache.Delete(key)
+ return nil
+ }
+ if val, ok := cache.Load(key); ok {
+ return val
+ }
+ if val := add(); val != nil {
+ cache.Store(key, val)
+ return val
+ }
+ return nil
+}
diff --git a/base/web/option.go b/base/web/option.go
index f0fe63ad..cfd840ec 100644
--- a/base/web/option.go
+++ b/base/web/option.go
@@ -21,9 +21,10 @@ func PushNotice(m *ice.Message, arg ...ice.Any) {
if m.Option(ice.MSG_DAEMON) == "" {
return
}
- m.Optionv(ice.MSG_OPTS, m.Optionv(ice.MSG_OPTION))
if m.Option(ice.MSG_USERPOD) == "" {
- m.Cmd(SPACE, m.Option(ice.MSG_DAEMON), arg)
+ msg := m.Spawn()
+ msg.Optionv(ice.MSG_OPTS, msg.Optionv(ice.MSG_OPTION, []string{}))
+ msg.Cmd(SPACE, m.Option(ice.MSG_DAEMON), arg)
} else {
opts := kit.Dict(ice.POD, m.Option(ice.MSG_DAEMON), "cmds", kit.Simple(arg...))
for _, k := range kit.Simple(m.Optionv(ice.MSG_OPTS)) {
@@ -66,8 +67,9 @@ func Toast(m *ice.Message, text string, arg ...ice.Any) { // [title [duration [p
}
PushNoticeToast(m, text, arg)
}
-func Toast3s(m *ice.Message, text string, arg ...ice.Any) {
+func Toast3s(m *ice.Message, text string, arg ...ice.Any) *ice.Message {
Toast(m, text, kit.List(kit.Select("", arg, 0), kit.Select("3s", arg, 1))...)
+ return m
}
func Toast30s(m *ice.Message, text string, arg ...ice.Any) {
Toast(m, text, kit.List(kit.Select("", arg, 0), kit.Select("30s", arg, 1))...)
diff --git a/base/web/render.go b/base/web/render.go
index fdd351eb..21aa4272 100644
--- a/base/web/render.go
+++ b/base/web/render.go
@@ -29,7 +29,9 @@ const (
)
func Render(m *ice.Message, cmd string, args ...ice.Any) bool {
- if cmd != "" {
+ if cmd == ice.RENDER_VOID {
+ return true
+ } else if cmd != "" {
defer func() { m.Logs(mdb.EXPORT, cmd, args) }()
}
@@ -69,9 +71,6 @@ func Render(m *ice.Message, cmd string, args ...ice.Any) bool {
RenderType(m.W, nfs.JSON, "")
m.W.Write([]byte(arg[0]))
- case ice.RENDER_VOID:
- // no output
-
default:
for _, k := range kit.Simple(m.Optionv("option"), m.Optionv("_option")) {
if m.Option(k) == "" {
diff --git a/misc/git/configs.go b/misc/git/configs.go
index 6e26f8d4..abf58ed6 100644
--- a/misc/git/configs.go
+++ b/misc/git/configs.go
@@ -1,10 +1,7 @@
package git
import (
- "strings"
-
ice "shylinux.com/x/icebergs"
- "shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits"
)
@@ -13,65 +10,56 @@ func _configs_set(m *ice.Message, key, value string) string {
return _git_cmds(m, "config", "--global", key, value)
}
func _configs_get(m *ice.Message, key string) string {
- if msg := _git_cmd(m, "config", "--global", key); cli.IsSuccess(msg) {
- return msg.Result()
- }
- return ""
+ return _git_cmds(m, "config", "--global", key)
}
func _configs_list(m *ice.Message) {
- for _, v := range strings.Split(_configs_get(m, "--list"), ice.NL) {
- if ls := strings.Split(v, "="); len(ls) > 1 {
- m.Push(mdb.NAME, ls[0])
- m.Push(mdb.VALUE, ls[1])
- m.PushButton(mdb.REMOVE)
- }
- }
- m.Sort(mdb.NAME)
-
- mdb.HashSelectValue(m, func(value ice.Maps) {
- m.Push("", value, kit.Split("name,value")).PushButton(mdb.CREATE)
+ kit.SplitKV(ice.EQ, ice.NL, _configs_get(m, "--list"), func(text string, ls []string) {
+ m.Push(mdb.NAME, ls[0]).Push(mdb.VALUE, ls[1]).PushButton(mdb.REMOVE)
})
+ mdb.HashSelectValue(m, func(value ice.Maps) { m.Push("", value, kit.Split("name,value")).PushButton(mdb.CREATE) })
+ m.StatusTimeCount()
}
const CONFIGS = "configs"
func init() {
- Index.Merge(&ice.Context{Configs: ice.Configs{
- CONFIGS: {Name: CONFIGS, Help: "配置键", Value: kit.Data(
+ Index.MergeCommands(ice.Commands{
+ CONFIGS: {Name: "configs name value auto create import", Help: "配置键", Actions: ice.MergeActions(ice.Actions{
+ mdb.IMPORT: {Help: "初始化", Hand: func(m *ice.Message, arg ...string) {
+ kit.Fetch(m.Configv(ice.INIT), func(p string, v ice.Any) {
+ kit.Fetch(v, func(k string, v string) { _configs_set(m, kit.Keys(p, k), v) })
+ })
+ }},
+ mdb.CREATE: {Name: "create name* value*", Hand: func(m *ice.Message, arg ...string) {
+ _configs_set(m, m.Option(mdb.NAME), m.Option(mdb.VALUE))
+ mdb.HashRemove(m, m.Option(mdb.NAME))
+ }},
+ mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) {
+ mdb.HashCreate(m.Spawn(), m.OptionSimple(mdb.NAME, mdb.VALUE))
+ _configs_set(m, "--unset", m.Option(mdb.NAME))
+ }},
+ mdb.MODIFY: {Hand: func(m *ice.Message, arg ...string) {
+ if arg[0] == mdb.VALUE {
+ mdb.HashRemove(m, m.Option(mdb.NAME))
+ _configs_set(m, m.Option(mdb.NAME), arg[1])
+ }
+ }},
+ }, mdb.HashAction(
mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,value", ice.INIT, kit.Dict(
"alias", kit.Dict("s", "status", "b", "branch", "l", "log --oneline --decorate"),
"credential", kit.Dict("helper", "store"),
"core", kit.Dict("quotepath", "false"),
"push", kit.Dict("default", "simple"),
"color", kit.Dict("ui", "always"),
- ))},
- }, Commands: ice.Commands{
- CONFIGS: {Name: "configs name auto create import", Help: "配置键", Actions: ice.Actions{
- mdb.IMPORT: {Name: "import", Help: "初始化", Hand: func(m *ice.Message, arg ...string) {
- kit.Fetch(m.Configv(ice.INIT), func(conf string, value ice.Any) {
- kit.Fetch(value, func(key string, value string) { _configs_set(m, kit.Keys(conf, key), value) })
- })
- }},
- mdb.CREATE: {Name: "create name value", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
- _configs_set(m, m.Option(mdb.NAME), m.Option(mdb.VALUE))
- mdb.HashRemove(m, m.Option(mdb.NAME))
- }},
- mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
- mdb.HashCreate(m.Spawn(), m.OptionSimple(mdb.NAME, mdb.VALUE))
- _configs_set(m, "--unset", m.Option(mdb.NAME))
- }},
- mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
- if arg[0] == mdb.VALUE {
- mdb.HashRemove(m, m.Option(mdb.NAME))
- _configs_set(m, m.Option(mdb.NAME), arg[1])
- }
- }},
- }, Hand: func(m *ice.Message, arg ...string) {
+ ),
+ )), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 {
_configs_list(m)
- } else {
+ } else if len(arg) == 1 {
m.Echo(_configs_get(m, arg[0]))
+ } else {
+ m.Echo(_configs_set(m, arg[0], arg[1]))
}
}},
- }})
+ })
}
diff --git a/misc/git/count.go b/misc/git/count.go
index e79706ee..7c5958bd 100644
--- a/misc/git/count.go
+++ b/misc/git/count.go
@@ -16,9 +16,7 @@ func _count_count(m *ice.Message, arg []string, cb func(string)) {
m.Echo("to many file, please choice sub dir")
return
}
- m.Option(nfs.DIR_DEEP, ice.TRUE)
- m.Option(nfs.DIR_TYPE, nfs.TYPE_CAT)
- m.Cmdy(nfs.DIR, arg, func(file string) {
+ m.Cmdy(nfs.DIR, arg, kit.Dict(nfs.DIR_DEEP, ice.TRUE, nfs.DIR_TYPE, nfs.TYPE_CAT), func(file string) {
if strings.Contains(file, "node_modules/") {
return
}
@@ -44,46 +42,35 @@ const COUNT = "count"
func init() {
Index.MergeCommands(ice.Commands{
COUNT: {Name: "count path auto count order tags", Help: "代码行", Actions: ice.Actions{
- "order": {Name: "order", Help: "排行", Hand: func(m *ice.Message, arg ...string) {
+ "order": {Help: "排行", Hand: func(m *ice.Message, arg ...string) {
files := map[string]int{}
_count_count(m, arg, func(file string) {
- m.Cmdy(nfs.CAT, file, func(text string, line int) {
- files[strings.TrimPrefix(file, arg[0])]++
- })
+ m.Cmdy(nfs.CAT, file, func(text string) { files[strings.TrimPrefix(file, arg[0])]++ })
})
- for k, n := range files {
- m.Push("files", k)
- m.Push("lines", n)
- }
+ kit.Fetch(files, func(k string, v int) { m.Push("files", k).Push("lines", v) })
m.StatusTimeCount().SortIntR("lines")
}},
- "tags": {Name: "tags", Help: "索引", Hand: func(m *ice.Message, arg ...string) {
+ "tags": {Help: "索引", Hand: func(m *ice.Message, arg ...string) {
count := map[string]int{}
- m.Cmd(nfs.CAT, path.Join(arg[0], "tags"), func(line string) {
- ls := strings.SplitN(line, ice.TB, 3)
- if len(ls) < 3 {
+ m.Cmd(nfs.CAT, path.Join(arg[0], nfs.TAGS), func(line string) {
+ if ls := strings.SplitN(line, ice.TB, 3); len(ls) < 3 {
return
- }
- ls = strings.SplitN(ls[2], ";\"", 2)
- if len(ls) < 2 {
+ } else if ls = strings.SplitN(ls[2], ";\"", 2); len(ls) < 2 {
return
+ } else {
+ count[kit.Split(ls[1])[0]]++
}
- ls = kit.Split(ls[1])
- count[ls[0]]++
})
- for k, v := range count {
- m.Push("type", k)
- m.Push("count", v)
- }
- m.SortIntR("count")
+ kit.Fetch(count, func(k string, v int) { m.Push(mdb.TYPE, k).Push(mdb.COUNT, v) })
+ m.SortIntR(mdb.COUNT)
}},
- COUNT: {Name: "count", Help: "计数", Hand: func(m *ice.Message, arg ...string) {
+ COUNT: {Help: "计数", Hand: func(m *ice.Message, arg ...string) {
files := map[string]int{}
lines := map[string]int{}
_count_count(m, arg, func(file string) {
files[mdb.TOTAL]++
files[kit.Ext(file)]++
- m.Cmdy(nfs.CAT, file, func(text string, line int) {
+ m.Cmdy(nfs.CAT, file, func(text string) {
if kit.Ext(file) == code.GO {
switch {
case strings.HasPrefix(text, "func"):
@@ -92,16 +79,11 @@ func init() {
lines["_type"]++
}
}
-
lines[mdb.TOTAL]++
lines[kit.Ext(file)]++
})
})
- for k := range lines {
- m.Push(mdb.TYPE, k)
- m.Push("files", files[k])
- m.Push("lines", lines[k])
- }
+ kit.Fetch(lines, func(k string, v int) { m.Push(mdb.TYPE, k).Push("files", files[k]).Push("lines", lines[k]) })
m.StatusTime().SortIntR("lines")
}},
}, Hand: func(m *ice.Message, arg ...string) { m.Cmdy(nfs.DIR, arg) }},
diff --git a/misc/git/git.go b/misc/git/git.go
index 24c1b68d..f09d38f1 100644
--- a/misc/git/git.go
+++ b/misc/git/git.go
@@ -1,26 +1,35 @@
package git
import (
+ "path"
+ "strings"
+
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web"
"shylinux.com/x/icebergs/core/code"
+ kit "shylinux.com/x/toolkits"
)
+func _git_url(m *ice.Message, repos string) string { return web.MergeLink(m, "/x/"+repos+".git") }
+func _git_dir(arg ...string) string { return path.Join(path.Join(arg...), ".git") }
func _git_cmd(m *ice.Message, arg ...string) *ice.Message { return m.Cmd(cli.SYSTEM, GIT, arg) }
-func _git_cmds(m *ice.Message, arg ...string) string { return _git_cmd(m, arg...).Result() }
+func _git_cmds(m *ice.Message, arg ...string) string {
+ msg := _git_cmd(m, arg...)
+ return kit.Select("", strings.TrimSpace(msg.Result()), !msg.IsErr())
+}
const GIT = "git"
var Index = &ice.Context{Name: GIT, Help: "代码库", Commands: ice.Commands{
GIT: {Name: "git path auto order build download", Help: "代码库", Actions: ice.MergeActions(ice.Actions{
- cli.ORDER: {Name: "order", Help: "加载", Hand: func(m *ice.Message, arg ...string) {
+ cli.ORDER: {Help: "加载", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(code.INSTALL, cli.ORDER, m.Config(nfs.SOURCE), "_install/libexec/git-core")
m.Cmdy(code.INSTALL, cli.ORDER, m.Config(nfs.SOURCE), "_install/bin")
}},
}, code.InstallAction(nfs.SOURCE, "http://mirrors.tencent.com/macports/distfiles/git-cinnabar/git-2.31.1.tar.gz")), Hand: func(m *ice.Message, arg ...string) {
- m.Cmdy(code.INSTALL, nfs.SOURCE, m.Config(nfs.SOURCE), arg)
+ m.Cmdy(code.INSTALL, m.ConfigSimple(nfs.SOURCE), arg)
}},
}}
diff --git a/misc/git/repos.go b/misc/git/repos.go
index 61e23543..4a8b44fd 100644
--- a/misc/git/repos.go
+++ b/misc/git/repos.go
@@ -1,6 +1,7 @@
package git
import (
+ "os"
"path"
"strings"
@@ -19,27 +20,34 @@ func _repos_path(name string) string {
return kit.Select(path.Join(ice.USR, name)+ice.PS, nfs.PWD, name == path.Base(kit.Pwd()))
}
func _repos_cmd(m *ice.Message, name string, arg ...string) *ice.Message {
- return m.Cmdy(cli.SYSTEM, GIT, arg, ice.Option{cli.CMD_DIR, _repos_path(name)})
+ m.Option(cli.CMD_DIR, _repos_path(name))
+ return m.Copy(_git_cmd(m, arg...))
}
-func _repos_insert(m *ice.Message, name string, dir string) {
- if s, e := nfs.StatFile(m, m.Option(cli.CMD_DIR, path.Join(dir, ".git"))); e == nil && s.IsDir() {
- ci, _ := gogit.OpenRepository(path.Join(dir, ".git")).GetCurrentCommit()
- mdb.HashCreate(m, mdb.NAME, name, nfs.PATH, dir,
- COMMIT, strings.TrimSpace(ci.CommitMessage), mdb.TIME, ci.Author.When.Format(ice.MOD_TIME),
- REMOTE, strings.SplitN(nfs.CatFile(m, path.Join(dir, ".git", "FETCH_HEAD")), ice.SP, 2)[1],
- BRANCH, path.Base(nfs.CatFile(m, path.Join(dir, ".git", "HEAD"))),
- )
+func _repos_init(m *ice.Message, p string) string {
+ os.MkdirAll(path.Join(p, "refs/heads/"), ice.MOD_DIR)
+ os.MkdirAll(path.Join(p, "objects/info/"), ice.MOD_DIR)
+ m.Cmd(nfs.SAVE, path.Join(p, "HEAD"), "ref: refs/heads/master")
+ return p
+}
+func _repos_insert(m *ice.Message, name string, path string) bool {
+ if repos, e := gogit.OpenRepository(_git_dir(path)); e == nil {
+ if ci, e := repos.GetCommit(); e == nil {
+ mdb.HashCreate(m, REPOS, name, nfs.PATH, path, mdb.TIME, ci.Author.When.Format(ice.MOD_TIME), COMMIT, strings.TrimSpace(ci.Message),
+ BRANCH, repos.GetBranch(), ORIGIN, kit.Select("", kit.Slice(kit.Split(repos.GetOrigin()), -1), 0))
+ } else {
+ mdb.HashCreate(m, REPOS, name, nfs.PATH, path, mdb.TIME, m.Time(),
+ BRANCH, repos.GetBranch(), ORIGIN, kit.Select("", kit.Slice(kit.Split(repos.GetOrigin()), -1), 0))
+ }
+ return true
}
+ return false
}
const (
- REMOTE = "remote"
ORIGIN = "origin"
BRANCH = "branch"
MASTER = "master"
-
- CLONE = "clone"
- INIT = "init"
+ INIT = "init"
)
const REPOS = "repos"
@@ -49,34 +57,39 @@ func init() {
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
m.Cmd(nfs.DIR, ice.USR, "name,path", func(value ice.Maps) { _repos_insert(m, value[mdb.NAME], value[nfs.PATH]) })
_repos_insert(m, path.Base(kit.Pwd()), kit.Pwd())
- cli.IsAlpine(m, GIT)
- cli.IsCentos(m, GIT)
- cli.IsUbuntu(m, GIT)
+ cli.IsSystem(m, GIT)
}},
- mdb.CREATE: {Name: "create repos branch name path", Hand: func(m *ice.Message, arg ...string) {
- m.OptionDefault(mdb.NAME, strings.TrimSuffix(path.Base(m.Option(REPOS)), ".git"))
+ INIT: {Hand: func(m *ice.Message, arg ...string) {
+ if dir := _repos_init(m, _git_dir(m.Option(cli.CMD_DIR))); m.Option(ORIGIN, kit.Select("", kit.Split(m.Option(ORIGIN)), -1)) != "" {
+ m.Cmd(nfs.SAVE, path.Join(dir, "config"), kit.Format(_repos_config, m.Option(ORIGIN)))
+ _git_cmd(m, PULL, ORIGIN, m.OptionDefault(BRANCH, MASTER))
+ }
+ }},
+ mdb.CREATE: {Name: "create origin name path", Hand: func(m *ice.Message, arg ...string) {
+ m.OptionDefault(mdb.NAME, strings.TrimSuffix(path.Base(m.Option(ORIGIN)), ".git"))
m.OptionDefault(nfs.PATH, path.Join(ice.USR, m.Option(mdb.NAME)))
- m.OptionDefault(REPOS, m.Config(REPOS)+m.Option(mdb.NAME))
- _repos_insert(m, m.Option(mdb.NAME), m.Option(nfs.PATH))
- if s, e := nfs.StatFile(m, path.Join(m.Option(nfs.PATH), ".git")); e == nil && s.IsDir() {
+ if _repos_insert(m, m.Option(mdb.NAME), m.Option(nfs.PATH)) {
return
}
- if s, e := nfs.StatFile(m, m.Option(nfs.PATH)); e == nil && s.IsDir() {
- m.Option(cli.CMD_DIR, m.Option(nfs.PATH))
- _git_cmd(m, INIT)
- _git_cmd(m, REMOTE, ADD, ORIGIN, m.Option(REPOS))
- _git_cmd(m, PULL, ORIGIN, kit.Select(MASTER, m.Option(BRANCH)))
- } else {
- m.Option(cli.CMD_DIR, "")
- _git_cmd(m, CLONE, "-b", kit.Select(MASTER, m.Option(BRANCH)), m.Option(REPOS), m.Option(nfs.PATH))
- }
+ m.Cmd("", INIT, kit.Dict(cli.CMD_DIR, m.Option(nfs.PATH)))
+ _repos_insert(m, m.Option(mdb.NAME), m.Option(nfs.PATH))
}},
- }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,branch,commit,remote", REPOS, "https://shylinux.com/x/"), mdb.ClearHashOnExitAction()), Hand: func(m *ice.Message, arg ...string) {
+ }, mdb.HashAction(mdb.SHORT, REPOS, mdb.FIELD, "time,repos,branch,commit,origin"), mdb.ClearHashOnExitAction()), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 {
- mdb.HashSelect(m, arg...).Sort(mdb.NAME).RenameAppend(mdb.NAME, REPOS)
+ mdb.HashSelect(m, arg...)
} else {
- m.Cmdy(nfs.DIR, kit.Select("", arg, 1), "time,line,path", kit.Dict(nfs.DIR_ROOT, _repos_path(arg[0])))
+ m.Cmdy(nfs.CAT, kit.Select(nfs.PWD, arg, 1), "time,line,path", kit.Dict(nfs.DIR_ROOT, _repos_path(arg[0])))
}
}},
})
}
+func ReposList(m *ice.Message) *ice.Message { return m.Cmd(REPOS, ice.OptionFields("repos,path")) }
+
+var _repos_config = `
+[remote "origin"]
+ url = %s
+ fetch = +refs/heads/*:refs/remotes/origin/*
+[branch "master"]
+ remote = origin
+ merge = refs/heads/master
+`
diff --git a/misc/git/server.go b/misc/git/server.go
index c7dfa29c..bcbd522b 100644
--- a/misc/git/server.go
+++ b/misc/git/server.go
@@ -6,7 +6,6 @@ import (
"encoding/base64"
"fmt"
"io"
- "net/http"
"path"
"strconv"
"strings"
@@ -22,26 +21,10 @@ import (
kit "shylinux.com/x/toolkits"
)
-func _server_rewrite(m *ice.Message, p string, r *http.Request) {
- if ua := r.Header.Get(web.UserAgent); strings.HasPrefix(ua, "Mozilla") {
- ls := kit.Split(r.URL.Path, "/")
- r.URL = kit.ParseURL(kit.MergeURL("/chat/cmd/web.code.inner", "path", "usr/"+ls[1]+"/", "file", path.Join(ls[2:]...)))
-
- // r.URL.Path = strings.Replace(r.URL.Path, "/x/", "/chat/pod/", 1)
- m.Info("rewrite %v -> %v", p, r.URL.Path) // 访问服务
-
- } else {
- r.URL.Path = strings.Replace(r.URL.Path, "/x/", "/code/git/repository/", 1)
- m.Info("rewrite %v -> %v", p, r.URL.Path) // 下载源码
- }
-}
func _server_login(m *ice.Message) error {
- if m.Conf("web.serve", kit.Keym(tcp.LOCALHOST)) != ice.FALSE {
- if tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP)) {
- return nil // 本机请求
- }
+ if tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP)) && m.Conf("web.serve", kit.Keym(tcp.LOCALHOST)) == ice.TRUE {
+ return nil
}
-
ls := strings.SplitN(m.R.Header.Get(web.Authorization), ice.SP, 2)
if strings.ToLower(ls[0]) != "basic" {
return fmt.Errorf("Authentication '%s' was not of 'Basic' type", ls[0])
@@ -50,43 +33,37 @@ func _server_login(m *ice.Message) error {
if err != nil {
return err
}
-
if ls = strings.SplitN(string(data), ice.DF, 2); !aaa.UserLogin(m, ls[0], ls[1]) {
- return fmt.Errorf("username or password error") // 登录失败
+ return fmt.Errorf("username or password error")
}
if aaa.UserRole(m, ls[0]) == aaa.VOID {
- return fmt.Errorf("userrole has no right") // 没有权限
+ return fmt.Errorf("userrole has no right")
}
return nil
}
func _server_param(m *ice.Message, arg ...string) (string, string) {
repos, service := path.Join(arg...), kit.Select(arg[len(arg)-1], m.Option("service"))
switch {
- case strings.HasSuffix(repos, "info/refs"):
- repos = strings.TrimSuffix(repos, "info/refs")
+ case strings.HasSuffix(repos, INFO_REFS):
+ repos = strings.TrimSuffix(repos, INFO_REFS)
default:
repos = strings.TrimSuffix(repos, service)
}
- return kit.Path(m.Config(nfs.PATH), REPOS, strings.TrimSuffix(repos, ".git/")), strings.TrimPrefix(service, "git-")
+ return kit.Path(ice.USR_LOCAL_REPOS, strings.TrimSuffix(repos, ".git/")), strings.TrimPrefix(service, "git-")
}
func _server_repos(m *ice.Message, arg ...string) error {
repos, service := _server_param(m, arg...)
-
- if m.Option(cli.CMD_DIR, repos); strings.HasSuffix(path.Join(arg...), "info/refs") {
+ if m.Option(cli.CMD_DIR, repos); strings.HasSuffix(path.Join(arg...), INFO_REFS) {
web.RenderType(m.W, "", kit.Format("application/x-git-%s-advertisement", service))
- msg := _git_cmd(m, service, "--stateless-rpc", "--advertise-refs", ice.PT)
- _server_writer(m, "# service=git-"+service+ice.NL, msg.Result())
+ _server_writer(m, "# service=git-"+service+ice.NL, _git_cmds(m, service, "--stateless-rpc", "--advertise-refs", ice.PT))
return nil
}
-
reader, err := _server_reader(m)
if err != nil {
return err
}
defer reader.Close()
-
- m.Option(cli.CMD_OUTPUT, m.W)
- m.Option(cli.CMD_INPUT, reader)
+ m.Options(cli.CMD_INPUT, reader, cli.CMD_OUTPUT, m.W)
web.RenderType(m.W, "", kit.Format("application/x-git-%s-result", service))
_git_cmd(m, service, "--stateless-rpc", ice.PT)
return nil
@@ -108,49 +85,43 @@ func _server_reader(m *ice.Message) (io.ReadCloser, error) {
return m.R.Body, nil
}
+const (
+ INFO_REFS = "info/refs"
+)
const SERVER = "server"
func init() {
- web.Index.MergeCommands(ice.Commands{"/x/": {Hand: func(m *ice.Message, arg ...string) { m.Cmdy("web.code.git.repository", arg) }}})
- Index.MergeCommands(ice.Commands{
- web.WEB_LOGIN: {Hand: func(m *ice.Message, arg ...string) { m.Render(ice.RENDER_VOID) }},
- "repository": {Name: "repository", Help: "代码库", Hand: func(m *ice.Message, arg ...string) {
- if m.Option("go-get") == "1" { // 下载地址
- p := web.MergeLink(m, "/x/"+path.Join(arg...))
- m.RenderResult(kit.Format(``, "go-import", kit.Format(`%s git %s`, strings.Split(p, "://")[1], p)))
+ web.Index.MergeCommands(ice.Commands{"/x/": {Actions: aaa.WhiteAction(), Hand: func(m *ice.Message, arg ...string) {
+ if m.RenderVoid(); m.Option("go-get") == "1" {
+ p := _git_url(m, path.Join(arg...))
+ m.RenderResult(kit.Format(``, kit.Format(`%s git %s`, strings.Split(p, "://")[1], p)))
+ return
+ }
+ switch repos, service := _server_param(m, arg...); service {
+ case "receive-pack":
+ if err := _server_login(m); m.Warn(err, ice.ErrNotLogin) {
+ web.RenderHeader(m.W, "WWW-Authenticate", `Basic realm="git server"`)
+ return
+ } else if !nfs.ExistsFile(m, repos) {
+ m.Logs(mdb.CREATE, REPOS, repos)
+ _repos_init(m, path.Join(ice.USR_LOCAL_REPOS, repos))
+ }
+ case "upload-pack":
+ if m.Warn(!nfs.ExistsFile(m, repos), ice.ErrNotFound, arg[0]) {
return
}
-
- switch repos, service := _server_param(m, arg...); service {
- case "receive-pack": // 上传代码
- if err := _server_login(m); err != nil {
- web.RenderHeader(m.W, "WWW-Authenticate", `Basic realm="git server"`)
- web.RenderStatus(m.W, http.StatusUnauthorized, err.Error())
- return // 没有权限
- }
- if !nfs.ExistsFile(m, repos) { // 创建仓库
- _git_cmd(m, INIT, "--bare", repos)
- m.Logs(mdb.CREATE, REPOS, repos)
- }
- case "upload-pack": // 下载代码
- if m.Warn(!nfs.ExistsFile(m, repos), ice.ErrNotFound, arg[0]) {
- return
- }
- }
-
- if err := _server_repos(m, arg...); err != nil {
- web.RenderStatus(m.W, http.StatusInternalServerError, err.Error())
- }
- }},
+ }
+ m.Warn(_server_repos(m, arg...), ice.ErrNotValid)
+ }}})
+ Index.MergeCommands(ice.Commands{
SERVER: {Name: "server path auto create import", Help: "服务器", Actions: ice.MergeActions(ice.Actions{
- mdb.CREATE: {Name: "create name", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
- m.Option(cli.CMD_DIR, ice.USR_LOCAL_REPOS)
- _git_cmd(m, INIT, "--bare", m.Option(mdb.NAME))
+ mdb.CREATE: {Name: "create name*", Hand: func(m *ice.Message, arg ...string) {
+ _repos_init(m, path.Join(ice.USR_LOCAL_REPOS, m.Option(mdb.NAME)))
}},
- mdb.IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
- m.Cmdy(REPOS, ice.OptionFields("time,name,path"), func(value ice.Maps) {
+ mdb.IMPORT: {Hand: func(m *ice.Message, arg ...string) {
+ ReposList(m).Tables(func(value ice.Maps) {
m.Option(cli.CMD_DIR, value[nfs.PATH])
- remote := web.MergeLink(m, "/x/"+value[REPOS])
+ remote := _git_url(m, value[REPOS])
_git_cmd(m, PUSH, remote, MASTER)
_git_cmd(m, PUSH, "--tags", remote, MASTER)
})
@@ -162,20 +133,15 @@ func init() {
web.DREAM_INPUTS: {Hand: func(m *ice.Message, arg ...string) {
switch arg[0] {
case nfs.REPOS:
- m.Cmd("web.code.git.server", func(value ice.Maps) {
- m.Push(nfs.PATH, web.MergeLink(m, path.Join("/x/", path.Clean(value[nfs.PATH])+".git")))
+ m.Cmd("", func(value ice.Maps) {
+ m.Push(nfs.PATH, _git_url(m, value[nfs.PATH]))
})
- m.Sort(nfs.PATH)
}
}},
}, gdb.EventAction(web.DREAM_INPUTS)), Hand: func(m *ice.Message, arg ...string) {
if m.Option(nfs.DIR_ROOT, ice.USR_LOCAL_REPOS); len(arg) == 0 {
- m.Cmdy(nfs.DIR, nfs.PWD, func(value ice.Maps) {
- m.PushScript("git clone " + web.MergeLink(m, "/x/"+path.Clean(value[nfs.PATH])))
- }).Cut("time,path,size,script,action")
- return
+ m.Cmdy(nfs.DIR, nfs.PWD, func(value ice.Maps) { m.PushScript("git clone " + _git_url(m, value[nfs.PATH]) }).Cut("time,path,size,script,action")
}
- m.Cmdy("_sum", path.Join(m.Option(nfs.DIR_ROOT), arg[0]))
}},
})
}
diff --git a/misc/git/spide.go b/misc/git/spide.go
index 1dfe87b3..6deff80d 100644
--- a/misc/git/spide.go
+++ b/misc/git/spide.go
@@ -5,130 +5,59 @@ import (
"strings"
ice "shylinux.com/x/icebergs"
+ "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
+ "shylinux.com/x/icebergs/base/web"
"shylinux.com/x/icebergs/core/code"
kit "shylinux.com/x/toolkits"
)
-func _spide_for(text string, cb func([]string)) {
- for _, line := range strings.Split(text, ice.NL) {
- if len(line) == 0 || strings.HasPrefix(line, "!_") {
- continue
- }
- cb(kit.Split(line, "\t ", "\t ", "\t "))
- }
-}
-func _spide_go(m *ice.Message, file string) {
- _spide_for(m.Cmdx(cli.SYSTEM, "gotags", file), func(ls []string) {
- switch ls[3] {
- case "i":
- return
- case "w", "e":
- return
- ls[0] = "-" + ls[0] + ice.DF + strings.TrimPrefix(ls[len(ls)-1], "type:")
- case "m":
- if strings.HasPrefix(ls[6], "ntype") {
- return
- } else if strings.HasPrefix(ls[5], "ctype") {
- ls[0] = strings.TrimPrefix(ls[5], "ctype:") + ice.DF + ls[0]
- } else {
- ls[0] = ls[3] + ice.DF + ls[0]
- }
- default:
- ls[0] = ls[3] + ice.DF + ls[0]
- }
-
- m.Push(mdb.NAME, ls[0])
- m.Push(nfs.FILE, ls[1])
- m.Push(nfs.LINE, strings.TrimSuffix(ls[2], ";\""))
- m.Push(mdb.TYPE, ls[3])
- m.Push(mdb.EXTRA, strings.Join(ls[4:], ice.SP))
- })
-}
-func _spide_c(m *ice.Message, file string) {
- _spide_for(m.Cmdx(cli.SYSTEM, "ctags", "-f", file), func(ls []string) {
- m.Push(mdb.NAME, ls[0])
- m.Push(nfs.FILE, ls[1])
- m.Push(nfs.LINE, "1")
- })
-}
-
const SPIDE = "spide"
func init() {
Index.MergeCommands(ice.Commands{
- SPIDE: {Name: "spide repos auto", Help: "构架图", Actions: ice.MergeActions(ice.Actions{
- "depend": {Name: "depend path=icebergs/base", Help: "依赖", Hand: func(m *ice.Message, arg ...string) {
- keys := map[string]bool{}
- list := map[string]map[string]bool{}
- dir := path.Join(ice.USR, m.Option(nfs.PATH)) + ice.PS
- _spide_for(m.Cmdx(cli.SYSTEM, "gotags", "-R", dir), func(ls []string) {
- if kit.Select("", ls, 3) != "i" {
+ SPIDE: {Name: "spide repos auto depend", Help: "构架图", Actions: ice.MergeActions(ice.Actions{
+ "depend": {Name: "depend path*=icebergs/base pkg=shy,all", Help: "依赖", Hand: func(m *ice.Message, arg ...string) {
+ list, keys := map[string]map[string]bool{}, map[string]bool{}
+ kit.SplitKV(ice.TB, ice.NL, m.Cmdx(cli.SYSTEM, "gotags", "-R", path.Join(ice.USR, m.Option(nfs.PATH)) + ice.PS), func(text string, ls []string) {
+ if strings.HasPrefix(text, "!_") {
+ return
+ } else if kit.Select("", ls, 3) != "i" {
+ return
+ } else if !strings.Contains(ls[0], m.Option(nfs.PATH)) && m.Option("pkg") == "shy" {
return
}
- if !strings.Contains(ls[0], m.Option(nfs.PATH)) {
- return
- }
-
item, ok := list[ls[0]]
if !ok {
item = map[string]bool{}
list[ls[0]] = item
}
-
p := strings.TrimPrefix(path.Dir(ls[1]), path.Join(ice.USR, m.Option(nfs.PATH)))
keys[p], item[p] = true, true
})
-
item := kit.SortedKey(keys)
-
for k, v := range list {
- m.Push("pkg", k)
- m.Push(mdb.COUNT, len(v))
+ m.Push("pkg", k).Push(mdb.COUNT, len(v))
for _, i := range item {
m.Push(i, kit.Select("", ice.OK, v[i]))
}
}
- m.SortIntR(mdb.COUNT)
- m.ProcessInner()
- }}, code.INNER: {Name: "web.code.inner"},
+ m.StatusTimeCount().SortIntR(mdb.COUNT)
+ }}, code.INNER: {Name: web.CODE_INNER},
}, ctx.CmdAction()), Hand: func(m *ice.Message, arg ...string) {
- if len(kit.Slice(arg, 0, 1)) == 0 { // 仓库列表
+ if len(kit.Slice(arg, 0, 1)) == 0 {
m.Cmdy(REPOS)
- return
- }
-
- if arg[0] = kit.Replace(arg[0], ice.SRC, ice.CONTEXTS); arg[0] == path.Base(kit.Pwd()) {
- m.Option(nfs.DIR_ROOT, path.Join(ice.SRC)+ice.PS)
- } else {
- m.Option(nfs.DIR_ROOT, path.Join(ice.USR, arg[0])+ice.PS)
- }
- ctx.DisplayStory(m, "spide.js", mdb.FIELD, nfs.PATH, "root", arg[0])
-
- if len(arg) == 1 { // 目录列表
- m.Option(nfs.DIR_DEEP, ice.TRUE)
+ } else if len(arg) == 1 {
color := []string{cli.YELLOW, cli.BLUE, cli.CYAN, cli.RED}
- nfs.Dir(m, nfs.PATH).Tables(func(value ice.Maps) {
+ ctx.DisplayStory(m, "spide.js", mdb.FIELD, nfs.PATH, aaa.ROOT, arg[0])
+ nfs.DirDeepAll(m, _repos_path(arg[0]), "", func(value ice.Maps) {
m.Push(cli.COLOR, color[strings.Count(value[nfs.PATH], ice.PS)%len(color)])
- })
- return
+ m.Push("", value, []string{nfs.PATH})
+ }, nfs.PATH)
}
- if arg[1] != arg[2] {
- return
- }
-
- // 语法解析
- switch m.Option(cli.CMD_DIR, m.Option(nfs.DIR_ROOT)); kit.Ext(arg[1]) {
- case code.GO:
- _spide_go(m, arg[1])
- case code.JS:
- default:
- _spide_c(m, arg[1])
- }
- m.SortInt(nfs.LINE)
}},
})
}
diff --git a/misc/git/status.go b/misc/git/status.go
index af97c628..0eaf365a 100644
--- a/misc/git/status.go
+++ b/misc/git/status.go
@@ -2,9 +2,11 @@ package git
import (
"path"
+ "runtime"
"strings"
"time"
+ "shylinux.com/x/gogit"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli"
@@ -18,6 +20,9 @@ import (
)
func _status_tag(m *ice.Message, tags string) string {
+ if tags == "" {
+ return "v0.0.1"
+ }
ls := kit.Split(strings.TrimPrefix(kit.Split(tags, "-")[0], "v"), ice.PT)
if v := kit.Int(ls[2]); v < 9 {
return kit.Format("v%v.%v.%v", ls[0], ls[1], v+1)
@@ -28,7 +33,7 @@ func _status_tag(m *ice.Message, tags string) string {
}
return "v0.0.1"
}
-func _status_tags(m *ice.Message, repos string) {
+func _status_tags(m *ice.Message) {
vs := ice.Maps{}
m.Cmd(STATUS, func(value ice.Maps) {
if value[mdb.TYPE] == "##" {
@@ -38,23 +43,15 @@ func _status_tags(m *ice.Message, repos string) {
vs[value[REPOS]] = strings.Split(value[TAGS], "-")[0]
}
})
-
web.GoToast(m, TAGS, func(toast func(string, int, int)) {
count, total := 0, len(vs)
- toast(cli.BEGIN, count, total)
- defer web.PushNoticeRefresh(m)
-
+ defer toast(ice.SUCCESS, count, count)
for k := range vs {
- if k != repos && repos != "" {
- continue
- }
- if k == ice.ICE {
+ if count++; k == ice.ICE {
k = ice.RELEASE
}
- count++
- toast(k, count, total)
-
change := false
+ toast(k, count, total)
m.Option(nfs.DIR_ROOT, _repos_path(k))
mod := m.Cmdx(nfs.CAT, ice.GO_MOD, func(text string, line int) string {
ls := kit.Split(strings.TrimPrefix(text, ice.REQUIRE))
@@ -63,61 +60,50 @@ func _status_tags(m *ice.Message, repos string) {
}
if v, ok := vs[kit.Slice(strings.Split(ls[0], ice.PS), -1)[0]]; ok && ls[1] != v {
m.Logs(mdb.MODIFY, REPOS, ls[0], "from", ls[1], "to", v)
- text = strings.ReplaceAll(text, ls[1], v)
- change = true
+ text, change = strings.ReplaceAll(text, ls[1], v), true
}
return text
})
- if !change || mod == "" {
+ if mod == "" || !change {
continue
}
-
- m.Cmd(nfs.SAVE, ice.GO_SUM, "")
m.Cmd(nfs.SAVE, ice.GO_MOD, mod)
switch m.Option(cli.CMD_DIR, _repos_path(k)); k {
case ice.RELEASE, ice.ICEBERGS, ice.TOOLKITS:
m.Cmd(cli.SYSTEM, code.GO, cli.BUILD)
+ case ice.CONTEXTS:
+ defer m.Cmd(cli.SYSTEM, cli.MAKE)
default:
m.Cmd(cli.SYSTEM, cli.MAKE)
}
}
- toast(ice.SUCCESS, count, count)
})
}
func _status_each(m *ice.Message, title string, cmds ...string) {
web.GoToast(m, title, func(toast func(string, int, int)) {
- count, total := 0, len(m.Confm(REPOS, mdb.HASH))
- toast(cli.BEGIN, count, total)
-
- list := []string{}
- m.Cmd(REPOS, ice.OptionFields("name,path"), func(value ice.Maps) {
+ list, count, total := []string{}, 0, len(m.Confm(REPOS, mdb.HASH))
+ ReposList(m).Tables(func(value ice.Maps) {
toast(value[REPOS], count, total)
-
- if msg := m.Cmd(cmds, ice.Option{cli.CMD_DIR, value[nfs.PATH]}); !cli.IsSuccess(msg) {
- web.Toast3s(m, msg.Append(cli.CMD_ERR), "error: "+value[REPOS])
+ if msg := m.Cmd(cmds, kit.Dict(cli.CMD_DIR, value[nfs.PATH])); !cli.IsSuccess(msg) {
+ web.Toast3s(m, msg.Append(cli.CMD_ERR), "error: "+value[REPOS]).Sleep3s()
list = append(list, value[REPOS])
- m.Sleep3s()
}
count++
})
-
if len(list) > 0 {
web.Toast30s(m, strings.Join(list, ice.NL), ice.FAILURE)
} else {
toast(ice.SUCCESS, count, total)
- web.PushNoticeRefresh(m)
}
})
- m.ProcessHold()
}
func _status_stat(m *ice.Message, files, adds, dels int) (int, int, int) {
- res := _git_cmds(m, DIFF, "--shortstat")
- for _, v := range kit.Split(res, ice.FS, ice.FS) {
+ for _, v := range kit.Split(_git_cmds(m, DIFF, "--shortstat") , ice.FS, ice.FS) {
n := kit.Int(kit.Split(strings.TrimSpace(v))[0])
switch {
case strings.Contains(v, "file"):
files += n
- case strings.Contains(v, "insert"):
+ case strings.Contains(v, "inser"):
adds += n
case strings.Contains(v, "delet"):
dels += n
@@ -126,19 +112,17 @@ func _status_stat(m *ice.Message, files, adds, dels int) (int, int, int) {
return files, adds, dels
}
func _status_list(m *ice.Message) (files, adds, dels int, last time.Time) {
- defer m.Sort("repos,type")
- m.Cmd(REPOS, ice.OptionFields("name,path")).Tables(func(value ice.Maps) {
- msg := m.Spawn(kit.Dict(cli.CMD_DIR, value[nfs.PATH]))
- diff := _git_cmds(msg, STATUS, "-sb")
- tags := _git_cmds(msg, "describe", "--tags")
- _files, _adds, _dels := _status_stat(msg, 0, 0, 0)
- now, _ := time.Parse("2006-01-02 15:04:05 -0700", strings.TrimSpace(_git_cmds(msg, "log", `--pretty=%cd`, "--date=iso", "-n1")))
-
- if files, adds, dels = files+_files, adds+_adds, dels+_dels; now.After(last) {
- last = now
+ ReposList(m).Tables(func(value ice.Maps) {
+ if m.Option(cli.CMD_DIR, value[nfs.PATH]); runtime.GOOS != cli.DARWIN {
+ files, adds, dels = _status_stat(m, files, adds, dels)
}
-
- for _, v := range strings.Split(strings.TrimSpace(diff), ice.NL) {
+ if repos, e := gogit.OpenRepository(_git_dir(value[nfs.PATH])); e == nil {
+ if ci, e := repos.GetCommit(); e == nil && ci.Author.When.After(last) {
+ last = ci.Author.When
+ }
+ }
+ tags := kit.Format(mdb.Cache(m, m.PrefixKey(value[REPOS], TAGS), func() ice.Any { return _git_cmds(m, "describe", "--tags") }))
+ for _, v := range strings.Split(strings.TrimSpace(_git_cmds(m, STATUS, "-sb")), ice.NL) {
if v == "" {
continue
}
@@ -147,42 +131,34 @@ func _status_list(m *ice.Message) (files, adds, dels int, last time.Time) {
case "swp", "swo", ice.BIN, ice.VAR:
continue
}
-
- m.Push(REPOS, value[REPOS])
- m.Push(mdb.TYPE, vs[0])
- m.Push(nfs.FILE, vs[1])
-
- list := []string{}
- switch vs[0] {
+ switch m.Push(REPOS, value[REPOS]).Push(mdb.TYPE, vs[0]).Push(nfs.FILE, vs[1]); vs[0] {
case "##":
- m.Push(TAGS, strings.TrimSpace(tags))
- if tags == ice.ErrWarn || tags == "" {
- list = append(list, TAG)
- }
-
- if strings.Contains(vs[1], "ahead") || !strings.Contains(vs[1], "...") {
- list = append(list, PUSH)
- } else if strings.Contains(tags, "-") {
- list = append(list, TAG)
+ if m.Push(TAGS, strings.TrimSpace(tags)); strings.Contains(vs[1], "ahead") || !strings.Contains(vs[1], "...") {
+ m.PushButton(PUSH)
+ } else if tags == "" || strings.Contains(tags, "-") {
+ m.PushButton(TAG)
+ } else {
+ m.PushButton("")
}
default:
- m.Push(TAGS, "")
- if strings.Contains(vs[0], "??") {
- list = append(list, ADD, nfs.TRASH)
+ if m.Push(TAGS, ""); strings.Contains(vs[0], "??") {
+ m.PushButton(ADD, nfs.TRASH)
} else {
- list = append(list, COMMIT)
+ m.PushButton(COMMIT)
}
}
- m.PushButton(list)
}
})
return
}
const (
- PULL = "pull"
- MAKE = "make"
- PUSH = "push"
+ PULL = "pull"
+ PUSH = "push"
+ DIFF = "diff"
+ TAGS = "tags"
+ STASH = "stash"
+ COMMIT = "commit"
ADD = "add"
OPT = "opt"
@@ -190,12 +166,8 @@ const (
TAG = "tag"
PIE = "pie"
- TAGS = "tags"
- DIFF = "diff"
- COMMIT = "commit"
COMMENT = "comment"
VERSION = "version"
- STASH = "stash"
)
const STATUS = "status"
@@ -204,118 +176,101 @@ func init() {
STATUS: {Name: "status repos auto", Help: "状态机", Actions: ice.MergeActions(ice.Actions{
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
switch arg[0] {
- case mdb.NAME, REPOS:
- m.Cmdy(REPOS).Cut(REPOS)
-
- case TAGS, VERSION:
- if m.Option(TAGS) == ice.ErrWarn {
- m.Push(VERSION, "v0.0.1")
- } else {
- m.Push(VERSION, _status_tag(m, m.Option(TAGS)))
- }
-
case COMMENT:
m.Push(mdb.TEXT, m.Option(nfs.FILE))
for _, v := range kit.Split(m.Option(nfs.FILE), " /") {
m.Push(mdb.TEXT, v)
}
+ case VERSION, TAGS:
+ if m.Option(TAGS) == "" {
+ m.Push(VERSION, "v0.0.1")
+ } else {
+ m.Push(VERSION, _status_tag(m, m.Option(TAGS)))
+ }
+ case aaa.EMAIL:
+ m.Push(arg[0], _configs_get(m, "user.email"))
case aaa.USERNAME:
m.Push(arg[0], kit.Select(m.Option(ice.MSG_USERNAME), _configs_get(m, "user.name")))
- case "email":
- m.Push(arg[0], _configs_get(m, "user.email"))
}
}},
CONFIGS: {Name: "configs email username", Help: "配置", Hand: func(m *ice.Message, arg ...string) {
_configs_set(m, "user.name", m.Option(aaa.USERNAME))
_configs_set(m, "user.email", m.Option(aaa.EMAIL))
}},
- CLONE: {Name: "clone repos='https://shylinux.com/x/volcanos' path=", Help: "克隆", Hand: func(m *ice.Message, arg ...string) {
+ INIT: {Name: "init origin*='https://shylinux.com/x/volcanos' name path", Help: "克隆", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(REPOS, mdb.CREATE)
}},
- PULL: {Name: "pull", Help: "下载", Hand: func(m *ice.Message, arg ...string) {
+ PULL: {Help: "下载", Hand: func(m *ice.Message, arg ...string) {
_status_each(m, PULL, cli.SYSTEM, GIT, PULL)
}},
- code.COMPILE: {Name: "compile", Help: "编译", Hand: func(m *ice.Message, arg ...string) {
- web.ToastProcess(m)
- defer web.ToastSuccess(m)
- m.Cmdy(code.VIMER, code.COMPILE)
- }},
- PUSH: {Name: "push", Help: "上传", Hand: func(m *ice.Message, arg ...string) {
+ PUSH: {Help: "上传", Hand: func(m *ice.Message, arg ...string) {
if m.Option(REPOS) == "" {
_status_each(m, PUSH, cli.SYSTEM, GIT, PUSH)
return
}
-
m.Option(cli.CMD_DIR, _repos_path(m.Option(REPOS)))
if strings.TrimSpace(_git_cmds(m, "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}")) == "" {
- _git_cmd(m, PUSH, "--set-upstream", "origin", "master")
+ _git_cmd(m, PUSH, "--set-upstream", ORIGIN, MASTER)
} else {
_git_cmd(m, PUSH)
}
_git_cmd(m, PUSH, "--tags")
}},
- TAGS: {Name: "tags", Help: "标签", Hand: func(m *ice.Message, arg ...string) {
- _status_tags(m, kit.Select("", arg, 0))
- m.ProcessHold()
- }},
- PIE: {Name: "pie", Help: "饼图", Hand: func(m *ice.Message, arg ...string) {
- m.Cmdy(TOTAL, PIE)
- }},
- STASH: {Name: "stash", Help: "缓存", Hand: func(m *ice.Message, arg ...string) {
- if len(arg) == 0 && m.Option(REPOS) == "" {
- _status_each(m, STASH, cli.SYSTEM, GIT, STASH)
- } else {
- _git_cmd(m, STASH)
- }
- }},
-
- ADD: {Name: "add", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
- _repos_cmd(m, m.Option(REPOS), ADD, m.Option(nfs.FILE)).SetAppend()
- }}, OPT: {Name: "opt", Help: "优化"}, PRO: {Name: "pro", Help: "升级"},
- COMMIT: {Name: "commit action=opt,add,pro comment=some@key", Help: "提交", Hand: func(m *ice.Message, arg ...string) {
- if arg[0] == ctx.ACTION {
- m.Option(mdb.TEXT, arg[1]+ice.SP+arg[3])
- } else {
- m.Option(mdb.TEXT, kit.Select("opt some", strings.Join(arg, ice.SP)))
- }
- _repos_cmd(m, m.Option(REPOS), COMMIT, "-am", m.Option(mdb.TEXT))
+ ADD: {Help: "添加", Hand: func(m *ice.Message, arg ...string) {
+ _repos_cmd(m, m.Option(REPOS), ADD, m.Option(nfs.FILE))
+ }}, OPT: {Help: "优化"}, PRO: {Help: "升级"},
+ COMMIT: {Name: "commit action=opt,add,pro comment=some", Help: "提交", Hand: func(m *ice.Message, arg ...string) {
+ _repos_cmd(m, m.Option(REPOS), COMMIT, "-am", m.Option("action")+ice.SP+m.Option(COMMENT))
+ mdb.Cache(m, m.PrefixKey(m.Option(REPOS), TAGS), nil)
m.ProcessBack()
}},
- TAG: {Name: "tag version@key", Help: "标签", Hand: func(m *ice.Message, arg ...string) {
+ TAG: {Name: "tag version", Help: "标签", Hand: func(m *ice.Message, arg ...string) {
if m.Option(VERSION) == "" {
m.Option(VERSION, _status_tag(m, m.Option(TAGS)))
}
_repos_cmd(m, m.Option(REPOS), TAG, m.Option(VERSION))
_repos_cmd(m, m.Option(REPOS), PUSH, "--tags")
- m.ProcessRefresh()
+ mdb.Cache(m, m.PrefixKey(m.Option(REPOS), TAGS), nil)
+ ctx.ProcessRefresh(m)
}},
- BRANCH: {Name: "branch", Help: "分支", Hand: func(m *ice.Message, arg ...string) {
+ TAGS: {Help: "标签", Hand: func(m *ice.Message, arg ...string) { _status_tags(m) }},
+ PIE: {Help: "饼图", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(TOTAL, PIE) }},
+ STASH: {Help: "缓存", Hand: func(m *ice.Message, arg ...string) {
+ if len(arg) == 0 && m.Option(REPOS) == "" {
+ _status_each(m, STASH, cli.SYSTEM, GIT, STASH)
+ } else {
+ _repos_cmd(m, kit.Select(m.Option(REPOS), arg, 0), STASH)
+ }
+ }},
+ BRANCH: {Help: "分支", Hand: func(m *ice.Message, arg ...string) {
for _, line := range kit.Split(_repos_cmd(m.Spawn(), arg[0], BRANCH).Result(), ice.NL, ice.NL) {
if strings.HasPrefix(line, "*") {
- m.Push(BRANCH, strings.TrimPrefix(line, "* "))
- m.PushButton("")
+ m.Push(BRANCH, strings.TrimPrefix(line, "* ")).PushButton("")
} else {
- m.Push(BRANCH, strings.TrimSpace(line))
- m.PushButton("branch_switch")
+ m.Push(BRANCH, strings.TrimSpace(line)).PushButton("branch_switch")
}
}
}},
- "branch_switch": {Name: "branch_switch", Help: "切换", Hand: func(m *ice.Message, arg ...string) {
- _repos_cmd(m.Spawn(), m.Option(REPOS), "checkout", m.Option(BRANCH))
- }},
- code.PUBLISH: {Name: "publish", Help: "发布", Hand: func(m *ice.Message, arg ...string) {
- m.Cmdy(code.PUBLISH, ice.CONTEXTS, ice.MISC, ice.CORE)
+ "branch_switch": {Help: "切换", Hand: func(m *ice.Message, arg ...string) {
+ _repos_cmd(m, m.Option(REPOS), "checkout", m.Option(BRANCH))
}},
nfs.TRASH: {Hand: func(m *ice.Message, arg ...string) {
nfs.Trash(m, path.Join(_repos_path(m.Option(REPOS)), m.Option(nfs.FILE)))
}},
- code.BINPACK: {Name: "binpack", Help: "发布模式", Hand: func(m *ice.Message, arg ...string) {
+ code.COMPILE: {Help: "编译", Hand: func(m *ice.Message, arg ...string) {
+ defer web.ToastProcess(m)()
+ m.Cmdy(code.VIMER, code.COMPILE)
+ }},
+ code.PUBLISH: {Help: "发布", Hand: func(m *ice.Message, arg ...string) {
+ m.Cmdy(code.PUBLISH, ice.CONTEXTS, ice.MISC, ice.CORE)
+ }},
+ code.BINPACK: {Help: "发布模式", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(nfs.LINK, ice.GO_SUM, path.Join(ice.SRC_RELEASE, ice.GO_SUM))
m.Cmd(nfs.LINK, ice.GO_MOD, path.Join(ice.SRC_RELEASE, ice.GO_MOD))
m.Cmdy(nfs.CAT, ice.GO_MOD)
m.Cmdy(code.VIMER, code.BINPACK)
}},
- code.DEVPACK: {Name: "devpack", Help: "开发模式", Hand: func(m *ice.Message, arg ...string) {
+ code.DEVPACK: {Help: "开发模式", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(code.VIMER, code.DEVPACK)
}},
web.DREAM_TABLES: {Hand: func(m *ice.Message, arg ...string) {
@@ -323,7 +278,7 @@ func init() {
return
}
text := []string{}
- for _, line := range kit.Split(m.Cmdx(web.SPACE, m.Option(mdb.NAME), cli.SYSTEM, "git", "diff", "--shortstat"), ice.FS, ice.FS) {
+ for _, line := range kit.Split(m.Cmdx(web.SPACE, m.Option(mdb.NAME), cli.SYSTEM, GIT, DIFF, "--shortstat"), ice.FS, ice.FS) {
if list := kit.Split(line); strings.Contains(line, "file") {
text = append(text, list[0]+" file")
} else if strings.Contains(line, "ins") {
@@ -336,24 +291,18 @@ func init() {
}},
}, gdb.EventAction(web.DREAM_TABLES), ctx.CmdAction(), aaa.RoleAction()), Hand: func(m *ice.Message, arg ...string) {
if _configs_get(m, "user.email") == "" {
- m.Echo("please config user.email")
- m.Action(CONFIGS)
- return
- }
- if len(arg) == 0 {
- web.ToastProcess(m, "status")
- m.Action(PULL, code.COMPILE, PUSH, TAGS, PIE, code.PUBLISH)
+ m.Echo("please config user.email").Action(CONFIGS)
+ } else if len(arg) == 0 {
+ defer web.ToastProcess(m)()
files, adds, dels, last := _status_list(m)
- m.Status("cost", m.FormatCost(), "repos", m.Length(), "files", files, "adds", adds, "dels", dels, "last", last.Format(ice.MOD_TIME))
- web.Toast3s(m, kit.Format("files: %d, adds: %d, dels: %d", files, adds, dels), ice.CONTEXTS)
- return
+ m.StatusTimeCount("files", files, "adds", adds, "dels", dels, "last", last.Format(ice.MOD_TIME))
+ m.Action(PULL, PUSH, TAGS, PIE, code.COMPILE, code.PUBLISH)
+ } else {
+ _repos_cmd(m, arg[0], DIFF)
+ files, adds, dels := _status_stat(m, 0, 0, 0)
+ m.StatusTime("files", files, "adds", adds, "dels", dels)
+ m.Action(COMMIT, TAGS, STASH, BRANCH)
}
-
- _repos_cmd(m, arg[0], DIFF)
- m.Action(COMMIT, TAGS, STASH, BRANCH)
- files, adds, dels := _status_stat(m, 0, 0, 0)
- m.Status("files", files, "adds", adds, "dels", dels)
- web.Toast3s(m, kit.Format("files: %d, adds: %d, dels: %d", files, adds, dels), arg[0])
}},
})
}
diff --git a/misc/git/total.go b/misc/git/total.go
index de628e30..af44e696 100644
--- a/misc/git/total.go
+++ b/misc/git/total.go
@@ -17,154 +17,113 @@ import (
const TOTAL = "total"
func init() {
- Index.Merge(&ice.Context{Configs: ice.Configs{
- TOTAL: {Name: TOTAL, Help: "统计量", Value: kit.Data(
- "skip", kit.Dict(
- "wubi-dict", ice.TRUE, "word-dict", ice.TRUE,
- "websocket", ice.TRUE, "go-qrcode", ice.TRUE,
- "go-sql-mysql", ice.TRUE, "echarts", ice.TRUE,
- ),
- )},
- }, Commands: ice.Commands{
- TOTAL: {Name: "total repos auto pie", Help: "统计量", Actions: ice.Actions{
- PIE: {Name: "pie", Help: "饼图", Hand: func(m *ice.Message, arg ...string) {
+ const (
+ FROM = "from"
+ DAYS = "days"
+ COMMIT = "commit"
+ ADDS = "adds"
+ DELS = "dels"
+ REST = "rest"
+ )
+ Index.MergeCommands(ice.Commands{
+ TOTAL: {Name: "total repos auto pie", Help: "统计量", Actions: ice.MergeActions(ice.Actions{
+ PIE: {Help: "饼图", Hand: func(m *ice.Message, arg ...string) {
defer ctx.DisplayStory(m, "pie.js")
- m.Cmd(TOTAL, func(value ice.Maps) {
- if value[REPOS] == mdb.TOTAL {
- m.StatusTimeCount(REPOS, mdb.TOTAL, mdb.VALUE, "1", mdb.TOTAL, value["rest"])
- return
+ m.Cmd("", func(value ice.Maps) {
+ if value[REPOS] != mdb.TOTAL {
+ m.Push(REPOS, value[REPOS]).Push(mdb.VALUE, value[REST]).Push("", value, []string{FROM, DAYS, COMMIT, ADDS, DELS})
}
- m.Push(REPOS, value[REPOS])
- m.Push(mdb.VALUE, value["rest"])
})
}},
- }, Hand: func(m *ice.Message, arg ...string) {
- if len(arg) > 0 { // 提交详情
- arg[0] = kit.Replace(arg[0], ice.SRC, ice.CONTEXTS)
- m.Cmd(REPOS, ice.OptionFields("name,path"), func(value ice.Maps) {
- if value[REPOS] == arg[0] {
- m.Cmdy("_sum", value[nfs.PATH], arg[1:])
- }
+ }, ctx.ConfAction("skip", kit.DictList("wubi-dict", "word-dict", "websocket", "go-qrcode", "go-sql-mysql", "echarts"))), Hand: func(m *ice.Message, arg ...string) {
+ if len(arg) > 0 {
+ ReposList(m).Tables(func(value ice.Maps) {
+ kit.If(value[REPOS] == arg[0], func() { m.Cmdy("_sum", value[nfs.PATH], arg[1:]) })
})
+ m.StatusTimeCount(FROM, m.Append(FROM))
return
}
-
- // 提交统计
from, days, commit, adds, dels, rest := "", 0, 0, 0, 0, 0
- m.Cmd(REPOS, ice.OptionFields("name,path")).TableGo(func(value ice.Maps, lock *task.Lock) {
+ ReposList(m).TableGo(func(value ice.Maps, lock *task.Lock) {
if m.Config(kit.Keys("skip", value[REPOS])) == ice.TRUE {
return
}
msg := m.Cmd("_sum", value[nfs.PATH], mdb.TOTAL, "10000")
- // msg := m.Cmd("_sum", value[nfs.PATH], mdb.TOTAL, "2022-01-01")
-
defer lock.Lock()()
msg.Tables(func(value ice.Maps) {
- if kit.Int(value["days"]) > days {
- days = kit.Int(value["days"])
- from = value["from"]
+ if kit.Int(value[DAYS]) > days {
+ from, days = value[FROM], kit.Int(value[DAYS])
}
- commit += kit.Int(value["commit"])
- adds += kit.Int(value["adds"])
- dels += kit.Int(value["dels"])
- rest += kit.Int(value["rest"])
+ commit += kit.Int(value[COMMIT])
+ adds += kit.Int(value[ADDS])
+ dels += kit.Int(value[DELS])
+ rest += kit.Int(value[REST])
})
-
- m.Push(REPOS, value[REPOS])
- m.Copy(msg)
+ m.Push(REPOS, value[REPOS]).Copy(msg)
})
-
- m.Push(REPOS, mdb.TOTAL)
- m.Push("tags", "v3.0.0")
- m.Push("days", days)
- m.Push("commit", commit)
- m.Push("adds", adds)
- m.Push("dels", dels)
- m.Push("rest", rest)
- m.SortIntR("rest")
- m.StatusTimeCount("from", from)
+ m.Push(REPOS, mdb.TOTAL).Push(TAGS, "v3.0.0").Push(FROM, from).Push(DAYS, days).Push(COMMIT, commit).Push(ADDS, adds).Push(DELS, dels).Push(REST, rest)
+ m.StatusTimeCount().SortIntR(REST)
}},
"_sum": {Name: "_sum [path] [total] [count|date] args...", Help: "统计量", Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 0 {
- if s, e := nfs.StatFile(m, path.Join(arg[0], ".git")); e == nil && s.IsDir() {
- m.Option(cli.CMD_DIR, arg[0])
- arg = arg[1:]
- } else if s, e := nfs.StatFile(m, path.Join(arg[0], "refs")); e == nil && s.IsDir() {
+ if nfs.ExistsFile(m, _git_dir(arg[0])) || nfs.ExistsFile(m, path.Join(arg[0], "refs/heads")) {
m.Option(cli.CMD_DIR, arg[0])
arg = arg[1:]
}
}
-
- total := false // 累积求和
+ total := false
if len(arg) > 0 && arg[0] == mdb.TOTAL {
total, arg = true, arg[1:]
}
-
args := []string{"log", "--shortstat", "--pretty=commit: %ad %n%s", "--date=iso", "--reverse"}
if len(arg) > 0 {
- if strings.Contains(arg[0], "-") && !strings.Contains(arg[0], ":") {
- arg[0] = arg[0] + " 00:00:00"
- }
+ arg[0] += kit.Select("", " 00:00:00", strings.Contains(arg[0], "-") && !strings.Contains(arg[0], ice.DF))
args = append(args, kit.Select("-n", "--since", strings.Contains(arg[0], "-")))
args = append(args, arg...)
} else {
args = append(args, "-n", "30")
}
-
- var total_day time.Duration
- from, count, count_add, count_del := "", 0, 0, 0
+ from, days, commit, adds, dels := "", time.Second, 0, 0, 0
for i, v := range strings.Split(_git_cmds(m, args...), "commit: ") {
- l := strings.Split(v, ice.NL)
- hs := strings.Split(l[0], ice.SP)
- if len(l) < 2 {
+ ls := strings.Split(strings.TrimSpace(v), ice.NL)
+ if len(ls) < 2 {
continue
}
-
add, del := "0", "0"
- if len(l) > 3 {
- for _, v := range kit.Split(strings.TrimSpace(l[3]), ice.FS) {
- switch {
- case strings.Contains(v, "insert"):
- add = kit.Split(v)[0]
- case strings.Contains(v, "delet"):
- del = kit.Split(v)[0]
- }
+ for _, v := range kit.Split(strings.TrimSpace(kit.Select("", ls, -1)), ice.FS) {
+ switch {
+ case strings.Contains(v, "inser"):
+ add = kit.Split(v)[0]
+ case strings.Contains(v, "delet"):
+ del = kit.Split(v)[0]
}
}
-
- if total { // 累积求和
- if count++; i == 1 {
+ hs := strings.Split(ls[0], ice.SP)
+ if total {
+ if commit++; i == 1 {
if t, e := time.Parse("2006-01-02", hs[0]); e == nil {
- total_day = time.Now().Sub(t)
- m.Append("from", hs[0])
+ from, days = hs[0], time.Now().Sub(t)
}
}
- count_add += kit.Int(add)
- count_del += kit.Int(del)
+ adds += kit.Int(add)
+ dels += kit.Int(del)
continue
}
-
- if i == 0 {
- from = hs[0]
- }
- m.Push("date", hs[0])
- m.Push("adds", add)
- m.Push("dels", del)
- m.Push("rest", kit.Int(add)-kit.Int(del))
- m.Push("note", l[1])
- m.Push("hour", strings.Split(hs[1], ":")[0])
- m.Push("time", hs[1])
+ m.Push(FROM, ls[0])
+ m.Push(ADDS, add)
+ m.Push(DELS, del)
+ m.Push(REST, kit.Int(add)-kit.Int(del))
+ m.Push(COMMIT, ls[1])
}
-
- if total { // 累积求和
- m.Push("from", from)
- m.Push("tags", _git_cmds(m, "describe", "--tags"))
- m.Push("days", int(total_day.Hours())/24)
- m.Push("commit", count)
- m.Push("adds", count_add)
- m.Push("dels", count_del)
- m.Push("rest", count_add-count_del)
+ if total {
+ m.Push(TAGS, _git_cmds(m, "describe", "--tags"))
+ m.Push(FROM, from)
+ m.Push(DAYS, int(days.Hours())/24)
+ m.Push(COMMIT, commit)
+ m.Push(ADDS, adds)
+ m.Push(DELS, dels)
+ m.Push(REST, adds-dels)
}
}},
- }})
+ })
}
diff --git a/misc/git/trend.go b/misc/git/trend.go
index b58adae6..d737ab0a 100644
--- a/misc/git/trend.go
+++ b/misc/git/trend.go
@@ -4,7 +4,6 @@ import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
- "shylinux.com/x/icebergs/core/code"
kit "shylinux.com/x/toolkits"
)
@@ -12,18 +11,15 @@ const TREND = "trend"
func init() {
Index.MergeCommands(ice.Commands{
- TREND: {Name: "trend repos@key begin_time@date auto", Help: "趋势图", Actions: ice.MergeActions(ice.Actions{
- mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
- m.Cmdy(REPOS, ice.OptionFields("name,time"))
- }}, code.INNER: {Name: "web.code.inner"},
- }, ctx.CmdAction()), Hand: func(m *ice.Message, arg ...string) {
- if len(arg) == 0 { // 仓库列表
+ TREND: {Name: "trend repos@key begin_time@date auto", Help: "趋势图", Actions: ice.Actions{
+ mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(REPOS, ice.OptionFields("repos,time")) }},
+ }, Hand: func(m *ice.Message, arg ...string) {
+ if len(arg) == 0 {
m.Cmdy(REPOS)
- return
+ } else {
+ m.Cmdy(TOTAL, kit.Slice(arg, 0, 2))
+ ctx.DisplayStory(m, "")
}
- arg[0] = kit.Replace(arg[0], ice.SRC, ice.CONTEXTS)
- m.Cmdy(TOTAL, kit.Slice(arg, 0, 2))
- ctx.DisplayStory(m, "trend.js")
}},
})
}
diff --git a/option.go b/option.go
index 3e67d631..804c8b2b 100644
--- a/option.go
+++ b/option.go
@@ -93,6 +93,10 @@ func (m *Message) Action(arg ...Any) *Message {
func (m *Message) Status(arg ...Any) *Message {
list, args := kit.List(), kit.Simple(arg)
for i := 0; i < len(args)-1; i += 2 {
+ switch args[i+1] {
+ case "", "0":
+ continue
+ }
list = append(list, kit.Dict(NAME, args[i], VALUE, args[i+1]))
}
m.Option(MSG_STATUS, kit.Format(list))
diff --git a/render.go b/render.go
index 985ba785..7571198e 100644
--- a/render.go
+++ b/render.go
@@ -111,6 +111,9 @@ func (m *Message) RenderResult(arg ...Any) *Message {
func (m *Message) RenderJson(arg ...Any) *Message {
return m.Render(RENDER_JSON, kit.Format(kit.Dict(arg...)))
}
+func (m *Message) RenderVoid(arg ...Any) *Message {
+ return m.Render(RENDER_VOID, arg...)
+}
func (m *Message) IsCliUA() bool {
if m.Option(MSG_USERUA) == "" || !strings.HasPrefix(m.Option(MSG_USERUA), "Mozilla") {