forked from x/icebergs
opt git
This commit is contained in:
parent
bff7fab4d6
commit
35c5a799f1
5
base/base.shy
Normal file
5
base/base.shy
Normal file
@ -0,0 +1,5 @@
|
||||
label `
|
||||
ctx mdb web aaa
|
||||
lex yac ssh gdb
|
||||
tcp nfs cli log
|
||||
`
|
@ -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()
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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))...)
|
||||
|
@ -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) == "" {
|
||||
|
@ -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]))
|
||||
}
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -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) }},
|
||||
|
@ -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)
|
||||
}},
|
||||
}}
|
||||
|
||||
|
@ -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
|
||||
`
|
||||
|
@ -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(`<meta name="%s" content="%s">`, "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(`<meta name="go-import" content="%s">`, 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]))
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
@ -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)
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
@ -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])
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
@ -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")
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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") {
|
||||
|
Loading…
x
Reference in New Issue
Block a user