diff --git a/base/aaa/aaa.go b/base/aaa/aaa.go index e69e9f04..2c8258ab 100644 --- a/base/aaa/aaa.go +++ b/base/aaa/aaa.go @@ -6,7 +6,9 @@ import ( ) const ( - RSA = "rsa" + RSA = "rsa" + SIGN = "sign" + VERIFY = "verify" ) const AAA = "aaa" diff --git a/base/nfs/dir.go b/base/nfs/dir.go index fc4952cc..be6837b1 100644 --- a/base/nfs/dir.go +++ b/base/nfs/dir.go @@ -36,7 +36,8 @@ func _dir_list(m *ice.Message, root string, dir string, level int, deep bool, di } p, pp := path.Join(root, dir, s.Name()), path.Join(dir, s.Name()) isDir := s.IsDir() || kit.IsDir(p) && deep == false - if !(dir_type == TYPE_CAT && isDir || dir_type == TYPE_DIR && !isDir) && (dir_reg == nil || dir_reg.MatchString(s.Name())) { + isBin := s.Mode().String()[3] == 'x' + if !(dir_type == TYPE_BIN && !isBin || dir_type == TYPE_CAT && isDir || dir_type == TYPE_DIR && !isDir) && (dir_reg == nil || dir_reg.MatchString(s.Name())) { switch cb := m.OptionCB("").(type) { case func(os.FileInfo, string): cb(s, p) @@ -131,6 +132,7 @@ const ( REQUIRE = "/require/" TYPE_ALL = "all" + TYPE_BIN = "bin" TYPE_CAT = "cat" TYPE_DIR = "dir" TYPE_BOTH = "both" diff --git a/base/nfs/trash.go b/base/nfs/trash.go index b309722c..ef711acb 100644 --- a/base/nfs/trash.go +++ b/base/nfs/trash.go @@ -35,7 +35,7 @@ func init() { mdb.HashRemove(m, m.OptionSimple(mdb.HASH)) }}, mdb.CREATE: {Hand: func(m *ice.Message, arg ...string) { - _trash_create(m, m.Option(FROM)) + _trash_create(m, kit.Paths(m.Option(FROM))) }}, mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) { Remove(m, m.Option(FILE)) @@ -48,4 +48,4 @@ func init() { }) } -func Trash(m *ice.Message, p string) *ice.Message { return m.Cmd(TRASH, mdb.CREATE, p) } +func Trash(m *ice.Message, p string, arg ...string) *ice.Message { return m.Cmd(TRASH, mdb.CREATE, p) } diff --git a/base/web/dream.go b/base/web/dream.go index 21c4250d..bfeeab4e 100644 --- a/base/web/dream.go +++ b/base/web/dream.go @@ -3,6 +3,7 @@ package web import ( "os" "path" + "runtime" "strings" ice "shylinux.com/x/icebergs" @@ -57,19 +58,29 @@ func _dream_show(m *ice.Message, name string) { ), cli.CMD_OUTPUT, path.Join(p, ice.VAR_LOG_BOOT_LOG), mdb.CACHE_CLEAR_ONEXIT, ice.TRUE) defer m.Options(cli.CMD_DIR, "", cli.CMD_ENV, "", cli.CMD_OUTPUT, "") gdb.Event(m, DREAM_CREATE, m.OptionSimple(mdb.NAME, mdb.TYPE)) - kit.If(m.Option(nfs.TEMPLATE), func() { _dream_template(m, p) }) + kit.If(m.Option(nfs.BINARY), func(p string) { _dream_binary(m, p) }) + kit.If(m.Option(nfs.TEMPLATE), func(p string) { _dream_template(m, p) }) m.Cmd(cli.DAEMON, kit.Select(kit.Path(os.Args[0]), cli.SystemFind(m, ice.ICE_BIN, nfs.PWD+path.Join(p, ice.BIN), nfs.PWD+ice.BIN)), SPACE, tcp.DIAL, ice.DEV, ice.OPS, mdb.TYPE, WORKER, m.OptionSimple(mdb.NAME), cli.DAEMON, ice.OPS) } +func _dream_binary(m *ice.Message, p string) { + if bin := path.Join(m.Option(cli.CMD_DIR), ice.BIN_ICE_BIN); kit.IsUrl(p) { + SpideSave(m, bin, kit.MergeURL(p, cli.GOOS, runtime.GOOS, cli.GOARCH, runtime.GOARCH), nil) + os.Chmod(bin, ice.MOD_DIR) + } else { + m.Cmd(nfs.LINK, bin, kit.Path(p)) + } +} func _dream_template(m *ice.Message, p string) { - kit.For([]string{ice.ETC_MISS_SH, + kit.For([]string{ ice.LICENSE, ice.MAKEFILE, ice.README_MD, ice.GO_MOD, ice.GO_SUM, - ice.SRC_MAIN_GO, ice.SRC_MAIN_SH, ice.SRC_MAIN_SHY, ice.SRC_MAIN_JS, + ice.SRC_MAIN_SH, ice.SRC_MAIN_SHY, ice.SRC_MAIN_GO, ice.SRC_MAIN_JS, + ice.ETC_MISS_SH, ice.ETC_INIT_SHY, ice.ETC_EXIT_SHY, }, func(file string) { - if nfs.Exists(m, path.Join(p, file)) { + if nfs.Exists(m, kit.Path(m.Option(cli.CMD_DIR), file)) { return } - switch m.Cmdy(nfs.COPY, path.Join(p, file), path.Join(ice.USR_LOCAL_WORK, m.Option(nfs.TEMPLATE), file)); file { + switch m.Cmdy(nfs.COPY, kit.Path(m.Option(cli.CMD_DIR), file), kit.Path(ice.USR_LOCAL_WORK, p, file)); file { case ice.GO_MOD: nfs.Rewrite(m, path.Join(p, file), func(line string) string { return kit.Select(line, nfs.MODULE+lex.SP+m.Option(mdb.NAME), strings.HasPrefix(line, nfs.MODULE)) @@ -101,20 +112,16 @@ func init() { switch arg[0] { case mdb.NAME, nfs.TEMPLATE: _dream_list(m).Cut("name,status,time") - case nfs.REPOS: - if msg := m.Cmd(SPIDE, ice.OPS, SPIDE_MSG, UserHost(m)+"/x/list"); !msg.IsErr() { - m.Copy(msg) - } - kit.For([]string{ice.OPS, ice.DEV, ice.SHY}, func(dev string) { - if msg := m.Cmd(SPIDE, dev, SPIDE_MSG, "/x/list"); !msg.IsErr() { - m.Copy(msg) - } + case nfs.BINARY: + m.Cmdy(nfs.DIR, ice.BIN, "path,size,hashs,time", kit.Dict(nfs.DIR_TYPE, nfs.TYPE_BIN)) + m.Cmd(nfs.DIR, ice.USR_LOCAL_WORK, func(value ice.Maps) { + m.Cmdy(nfs.DIR, path.Join(value[nfs.PATH], ice.BIN), "path,size,hashs,time", kit.Dict(nfs.DIR_TYPE, nfs.TYPE_BIN)) }) default: - gdb.Event(m, "", arg) + gdb.Event(m, DREAM_INPUTS, arg) } }}, - mdb.CREATE: {Name: "create name*=hi repos template", Hand: func(m *ice.Message, arg ...string) { + mdb.CREATE: {Name: "create name*=hi repos binary template", Hand: func(m *ice.Message, arg ...string) { m.Option(nfs.REPOS, kit.Select("", kit.Slice(kit.Split(m.Option(nfs.REPOS)), -1), 0)) _dream_show(m, m.OptionDefault(mdb.NAME, path.Base(m.Option(nfs.REPOS)))) }}, diff --git a/base/web/render.go b/base/web/render.go index ed793408..b3c64d5a 100644 --- a/base/web/render.go +++ b/base/web/render.go @@ -27,8 +27,10 @@ func Render(m *ice.Message, cmd string, args ...ice.Any) bool { } arg := kit.Simple(args...) kit.If(len(arg) == 0, func() { args = nil }) - if cmd != "" && (cmd != ice.RENDER_DOWNLOAD || m.R.Method != http.MethodGet) { - defer func() { m.Logs("Render", cmd, args) }() + if cmd != "" { + if cmd != ice.RENDER_DOWNLOAD || !kit.HasPrefix(arg[0], ice.USR_VOLCANOS, ice.USR_INTSHELL) { + defer func() { m.Logs("Render", cmd, args) }() + } } switch cmd { case COOKIE: // value [name [path [expire]]] diff --git a/base/web/serve.go b/base/web/serve.go index 5de00ac0..2bf8a536 100644 --- a/base/web/serve.go +++ b/base/web/serve.go @@ -21,7 +21,9 @@ import ( func _serve_address(m *ice.Message) string { return Domain(tcp.LOCALHOST, m.Option(tcp.PORT)) } func _serve_start(m *ice.Message) { - defer kit.For(kit.Split(m.Option(ice.DEV)), func(v string) { m.Sleep("10ms").Cmd(SPACE, tcp.DIAL, ice.DEV, v, mdb.NAME, ice.Info.NodeName) }) + defer kit.For(kit.Split(m.Option(ice.DEV)), func(v string) { + m.Sleep("10ms").Cmd(SPACE, tcp.DIAL, ice.DEV, v, mdb.NAME, ice.Info.NodeName, TOKEN, m.Option(TOKEN)) + }) kit.If(m.Option(aaa.USERNAME), func() { aaa.UserRoot(m, m.Option(aaa.USERNICK), m.Option(aaa.USERNAME)) }) kit.If(m.Option(tcp.PORT) == tcp.RANDOM, func() { m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT)) }) kit.If(cli.IsWindows(), func() { m.Cmd(SPIDE, ice.OPS, _serve_address(m)+"/exit").Sleep30ms() }) diff --git a/base/web/share.go b/base/web/share.go index 2bc8582c..326e05bc 100644 --- a/base/web/share.go +++ b/base/web/share.go @@ -19,6 +19,9 @@ import ( ) func _share_link(m *ice.Message, p string, arg ...ice.Any) string { + if strings.HasPrefix(p, ice.USR_PUBLISH) { + return tcp.PublishLocalhost(m, MergeLink(m, strings.TrimPrefix(p, ice.USR), arg...)) + } return tcp.PublishLocalhost(m, MergeLink(m, kit.Select("", PP(SHARE, LOCAL), !strings.HasPrefix(p, nfs.PS) && !strings.HasPrefix(p, HTTP))+p, arg...)) } func _share_cache(m *ice.Message, arg ...string) { @@ -129,6 +132,9 @@ func ShareLocalFile(m *ice.Message, arg ...string) { if m.Option(ice.POD) == "" { m.RenderDownload(p) return + } else if p := kit.Path(ice.USR_LOCAL_WORK, m.Option(ice.POD), p); nfs.Exists(m, p) { + m.RenderDownload(p) + return } pp := path.Join(ice.VAR_PROXY, m.Option(ice.POD), p) cache, size := time.Now().Add(-time.Hour*24), int64(0) diff --git a/base/web/space.go b/base/web/space.go index 761a2aef..8d3a6838 100644 --- a/base/web/space.go +++ b/base/web/space.go @@ -48,11 +48,18 @@ func _space_dial(m *ice.Message, dev, name string, arg ...string) { func _space_fork(m *ice.Message) { addr := kit.Select(m.R.RemoteAddr, m.R.Header.Get(ice.MSG_USERADDR)) name := kit.ReplaceAll(kit.Select(addr, m.Option(mdb.NAME)), "[", "_", "]", "_", nfs.DF, "_", nfs.PT, "_") - args := kit.Simple(mdb.TYPE, kit.Select(WORKER, m.Option(mdb.TYPE)), mdb.NAME, name, mdb.TEXT, kit.Select(addr, m.Option(mdb.TEXT)), m.OptionSimple(cli.DAEMON, ice.MSG_USERUA)) + text := kit.Select(addr, m.Option(mdb.TEXT)) + if kit.IsIn(m.Option(mdb.TYPE), CHROME) || !(ice.Info.Localhost && tcp.IsLocalHost(m, strings.Split(m.R.RemoteAddr, nfs.DF)[0]) || + m.Option(TOKEN) != "" && m.Cmdv(TOKEN, m.Option(TOKEN), mdb.TIME) > m.Time()) { + name = kit.ReplaceAll(addr, "[", "_", "]", "_", nfs.DF, "_", nfs.PT, "_") + text = kit.Select(addr, m.Option(mdb.NAME), m.Option(mdb.TEXT)) + } + args := kit.Simple(mdb.TYPE, kit.Select(WORKER, m.Option(mdb.TYPE)), mdb.NAME, name, mdb.TEXT, text, m.OptionSimple(cli.DAEMON, ice.MSG_USERUA)) if c, e := websocket.Upgrade(m.W, m.R); !m.Warn(e) { gdb.Go(m, func() { defer mdb.HashCreateDeferRemove(m, args, kit.Dict(mdb.TARGET, c))() switch m.Option(mdb.TYPE) { + case SERVER: case WORKER: defer gdb.EventDeferEvent(m, DREAM_OPEN, args)(DREAM_CLOSE, args) case CHROME: @@ -115,7 +122,11 @@ func _space_exec(m *ice.Message, source, target []string, c *websocket.Conn) { case cli.PWD: m.Push(mdb.LINK, m.MergePod(kit.Select("", source, -1))) default: - kit.If(aaa.Right(m, m.Detailv()), func() { m = m.Cmd() }) + kit.If(aaa.Right(m, m.Detailv()), func() { + m.TryCatch(m, true, func(_ *ice.Message) { + m = m.Cmd() + }) + }) } defer m.Cost(kit.Format("%v->%v %v %v", source, target, m.Detailv(), m.FormatSize())) _space_echo(m.Set(ice.MSG_OPTS).Options(log.DEBUG, m.Option(log.DEBUG)), []string{}, kit.Reverse(kit.Simple(source)), c) diff --git a/base/web/spide.go b/base/web/spide.go index 5ea1e33a..fca2a39d 100644 --- a/base/web/spide.go +++ b/base/web/spide.go @@ -54,11 +54,11 @@ func _spide_show(m *ice.Message, name string, arg ...string) { } defer res.Body.Close() m.Cost(cli.STATUS, res.Status, nfs.SIZE, res.Header.Get(ContentLength), mdb.TYPE, res.Header.Get(ContentType)) - kit.For(res.Header, func(k string, v []string) { m.Logs(mdb.IMPORT, k, v) }) + kit.For(res.Header, func(k string, v []string) { m.Logs("response", k, v) }) mdb.HashSelectUpdate(m, name, func(value ice.Map) { kit.For(res.Cookies(), func(v *http.Cookie) { kit.Value(value, kit.Keys(SPIDE_COOKIE, v.Name), v.Value) - m.Logs(mdb.IMPORT, v.Name, v.Value) + m.Logs("response", v.Name, v.Value) }) }) if m.Warn(res.StatusCode != http.StatusOK, ice.ErrNotValid, uri, cli.STATUS, res.Status) { diff --git a/base/web/token.go b/base/web/token.go new file mode 100644 index 00000000..10a0de39 --- /dev/null +++ b/base/web/token.go @@ -0,0 +1,19 @@ +package web + +import ( + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/mdb" + kit "shylinux.com/x/toolkits" +) + +const TOKEN = "token" + +func init() { + Index.MergeCommands(ice.Commands{ + TOKEN: {Name: "token hash auto create prunes", Help: "令牌", Actions: ice.MergeActions(mdb.HashAction(mdb.EXPIRE, mdb.MONTH, mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,type,name,text")), Hand: func(m *ice.Message, arg ...string) { + if mdb.HashSelect(m, arg...); len(arg) > 0 { + m.Cmdy("web.code.publish", ice.CONTEXTS, kit.Dict(TOKEN, arg[0])) + } + }}, + }) +} diff --git a/core/chat/favor.go b/core/chat/favor.go index b5d93580..9c7437e9 100644 --- a/core/chat/favor.go +++ b/core/chat/favor.go @@ -104,7 +104,7 @@ func init() { m.Option(mdb.TYPE, mdb.HashSelects(m.Spawn(), m.Option(mdb.HASH)).Append(mdb.TYPE)) ctx.Run(m, arg...) }}, - }, ctx.CmdAction(), mdb.HashAction(), mdb.ImportantDataAction(), KeyboardAction()), Hand: func(m *ice.Message, arg ...string) { + }, ctx.CmdAction(), mdb.HashAction(), mdb.ImportantDataAction()), Hand: func(m *ice.Message, arg ...string) { if len(arg) > 0 && arg[0] == ctx.ACTION { m.Option(mdb.TYPE, mdb.HashSelects(m.Spawn(), m.Option(mdb.HASH)).Append(mdb.TYPE)) gdb.Event(m, FAVOR_ACTION, arg) diff --git a/core/chat/pod.go b/core/chat/pod.go index b9ab0a39..8a7b3f17 100644 --- a/core/chat/pod.go +++ b/core/chat/pod.go @@ -2,6 +2,7 @@ package chat import ( "path" + "strings" ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/aaa" @@ -18,12 +19,12 @@ const POD = "pod" func init() { Index.MergeCommands(ice.Commands{ POD: {Name: "pod", Help: "节点", Actions: ice.MergeActions(ctx.CmdAction(), web.ApiAction(), aaa.WhiteAction()), Hand: func(m *ice.Message, arg ...string) { - if web.AgentIs(m, "curl", "wget") { - m.Cmdy(web.SHARE_LOCAL, ice.BIN_ICE_BIN, kit.Dict(ice.POD, kit.Select("", arg, 0), ice.MSG_USERROLE, aaa.TECH)) - return - } if len(arg) == 0 || kit.Select("", arg, 0) == "" { web.RenderCmd(m, web.SPACE) + } else if strings.HasPrefix(m.Option(ice.MSG_USERUA), "git/") { + m.RenderRedirect(m.Cmdv(web.SPACE, arg[0], "web.code.git.repos", nfs.REMOTE, nfs.REMOTE) + "/info/refs?service=" + m.Option("service")) + } else if m.Option(cli.GOOS) != "" && m.Option(cli.GOARCH) != "" { + m.RenderDownload(path.Join(ice.USR_LOCAL_WORK, arg[0], ice.USR_PUBLISH, kit.Keys(ice.ICE, m.Option(cli.GOOS), m.Option(cli.GOARCH)))) } else if len(arg) == 1 { if m.Cmd(web.SPACE, arg[0]).Length() == 0 && nfs.Exists(m, path.Join(ice.USR_LOCAL_WORK, arg[0])) { m.Cmd(web.DREAM, cli.START, kit.Dict(mdb.NAME, arg[0])) diff --git a/core/code/autogen.go b/core/code/autogen.go index 7a7460de..dc3b2563 100644 --- a/core/code/autogen.go +++ b/core/code/autogen.go @@ -53,7 +53,7 @@ func _autogen_import(m *ice.Message, main string, ctx string, mod string) { } func _autogen_version(m *ice.Message) string { if mod := _autogen_mod(m, ice.GO_MOD); !nfs.Exists(m, ".git") { - m.Cmd(REPOS, "init", nfs.ORIGIN, kit.Select(m.Option(ice.MSG_USERHOST), ice.Info.Make.Domain)+"/x/"+path.Base(mod), mdb.NAME, path.Base(mod), nfs.PATH, nfs.PWD) + m.Cmd(REPOS, "init", nfs.ORIGIN, strings.Split(kit.MergeURL2(kit.Select(ice.Info.Make.Remote, ice.Info.Make.Domain), "/x/"+path.Base(mod)), mdb.QS)[0], mdb.NAME, path.Base(mod), nfs.PATH, nfs.PWD) defer m.Cmd(REPOS, "add", kit.Dict(nfs.REPOS, path.Base(mod), nfs.FILE, nfs.SRC)) defer m.Cmd(REPOS, "add", kit.Dict(nfs.REPOS, path.Base(mod), nfs.FILE, "go.mod")) } @@ -74,14 +74,11 @@ func _autogen_gits(m *ice.Message, arg ...string) string { return kit.Join(res, lex.NL) } func _autogen_git(m *ice.Message, arg ...string) ice.Map { + msg := m.Cmd("web.code.git.repos", "remote") return kit.Dict(arg, - mdb.TIME, m.Time(), nfs.PATH, kit.Path(""), web.DOMAIN, web.UserHost(m), - mdb.HASH, m.Cmdx(cli.SYSTEM, GIT, "log", "-n1", `--pretty=%H`), - nfs.REMOTE, m.Cmdx(cli.SYSTEM, GIT, "config", "remote.origin.url"), - nfs.BRANCH, m.Cmdx(cli.SYSTEM, GIT, "rev-parse", "--abbrev-ref", "HEAD"), - nfs.VERSION, m.Cmdx(cli.SYSTEM, GIT, "describe", "--tags"), - aaa.EMAIL, m.Cmdx(cli.SYSTEM, GIT, "config", "user.email"), - aaa.USERNAME, kit.Select(ice.Info.Username, m.Cmdx(cli.SYSTEM, GIT, "config", "user.name")), + mdb.TIME, m.Time(), nfs.PATH, kit.Path(""), web.DOMAIN, tcp.PublishLocalhost(m, m.Option(ice.MSG_USERWEB)), + mdb.HASH, msg.Append(mdb.HASH), nfs.REMOTE, msg.Append(nfs.REMOTE), nfs.BRANCH, msg.Append(nfs.BRANCH), nfs.VERSION, msg.Append(nfs.VERSION), + aaa.EMAIL, msg.Append(aaa.EMAIL), aaa.USERNAME, msg.Append(aaa.USERNAME), ) } func _autogen_mod(m *ice.Message, file string) (mod string) { diff --git a/core/code/go.go b/core/code/go.go index d40d5cef..68930910 100644 --- a/core/code/go.go +++ b/core/code/go.go @@ -118,7 +118,6 @@ func init() { ProcessXterm(m, cmds, text, arg[1]) }}, mdb.ENGINE: {Hand: func(m *ice.Message, arg ...string) { - m.Cmd(yac.STACK, kit.Simple(path.Join(arg[2], arg[1]))) if cmd := ctx.GetFileCmd(path.Join(arg[2], arg[1])); cmd != "" { ctx.ProcessCommand(m, cmd, kit.Simple()) return diff --git a/core/code/upgrade.go b/core/code/upgrade.go index 3ffe6980..92922957 100644 --- a/core/code/upgrade.go +++ b/core/code/upgrade.go @@ -7,6 +7,7 @@ import ( ice "shylinux.com/x/icebergs" "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" @@ -21,28 +22,33 @@ func init() { nfs.TARGET, kit.Dict(mdb.LIST, kit.List(mdb.TYPE, ice.BIN, nfs.FILE, ice.ICE_BIN)), nfs.BINARY, kit.Dict(mdb.LIST, kit.List(mdb.TYPE, nfs.TAR, nfs.FILE, "contexts.bin.tar.gz")), nfs.SOURCE, kit.Dict(mdb.LIST, kit.List(mdb.TYPE, nfs.TAR, nfs.FILE, "contexts.src.tar.gz")), + ctx.CONFIG, kit.Dict(mdb.LIST, kit.List(mdb.TYPE, nfs.SHY, nfs.FILE, ice.ETC_LOCAL_SHY)), COMPILE, kit.Dict(mdb.LIST, kit.List(mdb.TYPE, nfs.TAR, nfs.FILE, "go1.15.5", nfs.PATH, ice.USR_LOCAL)), ), mdb.META, kit.Dict(mdb.FIELD, "type,file,path"))}, }, Commands: ice.Commands{ - UPGRADE: {Name: "upgrade item=target,binary,source,compile run restart", Help: "升级", Actions: ice.MergeActions(ice.Actions{ + UPGRADE: {Name: "upgrade item=target,config,binary,source,compile run restart", Help: "升级", Actions: ice.MergeActions(ice.Actions{ cli.RESTART: {Hand: func(m *ice.Message, arg ...string) { m.Go(func() { m.Sleep300ms(ice.EXIT, 1) }) }}, }), Hand: func(m *ice.Message, arg ...string) { mdb.ZoneSelect(m.Spawn(), kit.Select(nfs.TARGET, arg, 0)).Table(func(value ice.Maps) { - if value[nfs.FILE] == ice.ICE_BIN { + if kit.Select("", arg, 0) == COMPILE { + value[nfs.FILE] = kit.Keys(kit.Format(value[nfs.FILE]), runtime.GOOS+"-"+runtime.GOARCH, kit.Select("tar.gz", "zip", runtime.GOOS == cli.WINDOWS)) + } + if value[nfs.FILE] == ice.ICE_BIN && os.Getenv(cli.CTX_POD) == "" { value[nfs.FILE] = kit.Keys(ice.ICE, runtime.GOOS, runtime.GOARCH) defer nfs.Rename(m, value[nfs.FILE], ice.BIN_ICE_BIN) m.Option(ice.EXIT, ice.TRUE) } - if kit.Select("", arg, 0) == COMPILE { - value[nfs.FILE] = kit.Keys(kit.Format(value[nfs.FILE]), runtime.GOOS+"-"+runtime.GOARCH, kit.Select("tar.gz", "zip", runtime.GOOS == cli.WINDOWS)) + uri := "/publish/" + kit.Format(value[nfs.FILE]) + if os.Getenv(cli.CTX_POD) != "" { + uri = kit.MergeURL2(os.Getenv(cli.CTX_DEV), "/chat/pod/"+os.Getenv(cli.CTX_POD), cli.GOOS, runtime.GOOS, cli.GOARCH, runtime.GOARCH) } dir := path.Join(kit.Format(value[nfs.PATH]), kit.Format(value[nfs.FILE])) - switch web.SpideSave(m, dir, "/publish/"+kit.Format(value[nfs.FILE]), nil); value[mdb.TYPE] { + switch web.SpideSave(m, dir, uri, nil); value[mdb.TYPE] { case nfs.TAR: m.Cmd(cli.SYSTEM, nfs.TAR, "xf", dir, "-C", path.Dir(dir)) // m.Cmd(nfs.TAR, mdb.EXPORT, dir, "-C", path.Dir(dir)) case ice.BIN: - os.Chmod(dir, 0755) + os.Chmod(dir, ice.MOD_DIR) } m.Cmdy(nfs.DIR, dir, "time,size,path,hash") }) diff --git a/exec.go b/exec.go index 4645cf24..ee0e55b6 100644 --- a/exec.go +++ b/exec.go @@ -83,7 +83,7 @@ func (m *Message) Cmdv(arg ...Any) string { } func (m *Message) Cmdx(arg ...Any) string { res := strings.TrimSpace(kit.Select("", m._command(arg...).meta[MSG_RESULT], 0)) - return kit.Select("", res, res != ErrWarn) + return kit.Select("", res, res != strings.TrimSpace(ErrWarn)) } func (m *Message) Cmdy(arg ...Any) *Message { return m.Copy(m._command(arg...)) } func (m *Message) CmdHand(cmd *Command, key string, arg ...string) *Message { diff --git a/info.go b/info.go index 08ab9967..5dac4f7d 100644 --- a/info.go +++ b/info.go @@ -105,6 +105,7 @@ func MergeActions(arg ...Any) Actions { h = list[CTX_INIT] } h.Hand = MergeHand(h.Hand, func(m *Message, arg ...string) { + _cmd := m._cmd m.Search(from, func(p *Context, s *Context, key string, cmd *Command) { for k, v := range cmd.Actions { func(k string) { @@ -113,6 +114,12 @@ func MergeActions(arg ...Any) Actions { } else if h.Hand == nil { h.Hand = func(m *Message, arg ...string) { m.Cmdy(from, k, arg) } } + if help := kit.Split(v.Help, " ::"); len(help) > 0 { + if kit.Value(_cmd.Meta, kit.Keys("_trans", strings.TrimPrefix(k, "_")), help[0]); len(help) > 1 { + kit.Value(_cmd.Meta, kit.Keys("_title", k), help[1]) + } + } + kit.If(len(v.List) > 0, func() { _cmd.Meta[k] = v.List }) }(k) } }) diff --git a/misc/git/repos.go b/misc/git/repos.go index 5bd8fbae..2585e5e5 100644 --- a/misc/git/repos.go +++ b/misc/git/repos.go @@ -18,6 +18,7 @@ import ( "shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/ctx" + "shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/lex" "shylinux.com/x/icebergs/base/log" "shylinux.com/x/icebergs/base/mdb" @@ -347,6 +348,17 @@ func init() { m.PushSearch(mdb.TYPE, web.LINK, mdb.NAME, m.CommandKey(), mdb.TEXT, m.MergePodCmd("", "", log.DEBUG, ice.TRUE)) } }}, + mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { + switch arg[0] { + case COMMENT: + ls := kit.Split(m.Option(nfs.FILE), " /") + m.Push(arg[0], kit.Join(kit.Slice(ls, -1), nfs.PS)) + m.Push(arg[0], kit.Join(kit.Slice(ls, -2), nfs.PS)) + m.Push(arg[0], m.Option(nfs.FILE)) + case VERSION: + m.Push(VERSION, _status_tag(m, m.Option(TAGS))) + } + }}, INIT: {Name: "clone origin* branch name path", Hand: func(m *ice.Message, arg ...string) { m.Cmd(nfs.DEFS, kit.Path(".git/config"), nfs.Template(m, "config", m.Option("origin"))) git.PlainInit(m.Option(nfs.PATH), false) @@ -359,7 +371,7 @@ func init() { _repos_insert(m, m.Option(nfs.PATH)) } }}, - PULL: {Hand: func(m *ice.Message, arg ...string) { + PULL: {Help: "下载", Hand: func(m *ice.Message, arg ...string) { _repos_each(m, "", func(repos *git.Repository, value ice.Maps) error { if value[ORIGIN] == "" { return nil @@ -370,14 +382,15 @@ func init() { } }) }}, - PUSH: {Hand: func(m *ice.Message, arg ...string) { + PUSH: {Help: "上传", Hand: func(m *ice.Message, arg ...string) { list := _repos_credentials(m) _repos_each(m, "", func(repos *git.Repository, value ice.Maps) error { if value[ORIGIN] == "" { return nil } - u := list[kit.ParseURL(value[ORIGIN]).Host] - if password, ok := u.User.Password(); !ok { + if u, ok := list[kit.ParseURL(value[ORIGIN]).Host]; !ok { + return errors.New("not found userinfo") + } else if password, ok := u.User.Password(); !ok { return errors.New("not found password") } else { return repos.Push(&git.PushOptions{Auth: &http.BasicAuth{Username: u.User.Username(), Password: password}}) @@ -405,7 +418,7 @@ func init() { } }}, STASH: {Hand: func(m *ice.Message, arg ...string) { _repos_cmd(m, kit.Select(m.Option(REPOS), arg, 0), STASH) }}, - COMMIT: {Name: "commit actions=add,opt,fix comment*=some", Hand: func(m *ice.Message, arg ...string) { + COMMIT: {Name: "commit actions=add,opt,fix comment*=some", Help: "提交", Hand: func(m *ice.Message, arg ...string) { if work, err := _repos_open(m, m.Option(REPOS)).Worktree(); !m.Warn(err) { opt := &git.CommitOptions{All: true} if cfg, err := config.LoadConfig(config.GlobalScope); err == nil { @@ -444,6 +457,25 @@ func init() { m.Sort("repos,status,file").Status(mdb.TIME, last, kit.Select(aaa.TECH, aaa.VOID, password == ""), m.Option(aaa.EMAIL), REMOTE, remote, kit.MDB_COUNT, kit.Split(m.FormatSize())[0], kit.MDB_COST, m.FormatCost()) } }}, + REMOTE: {Hand: func(m *ice.Message, arg ...string) { + repos := _repos_open(m, kit.Select(path.Base(kit.Path("")), kit.Select(m.Option(REPOS), arg, 0))) + if _remote, err := repos.Remote(ORIGIN); err == nil { + m.Push(REMOTE, kit.Select("", _remote.Config().URLs, 0)) + } + if refer, err := repos.Head(); err == nil { + m.Push(BRANCH, strings.TrimPrefix(refer.Name().String(), "refs/heads/")) + m.Push(mdb.HASH, refer.Hash().String()) + } + if iter, err := repos.Tags(); err == nil { + if refer, err := iter.Next(); err == nil { + m.Push(nfs.VERSION, strings.TrimPrefix(refer.Name().String(), "refs/tags/")) + } + } + if cfg, err := config.LoadConfig(config.GlobalScope); err == nil { + m.Push(aaa.EMAIL, kit.Select(m.Option(ice.MSG_USERNAME)+"@163.com", cfg.User.Email)) + m.Push(aaa.USERNAME, kit.Select(m.Option(ice.MSG_USERNAME), cfg.User.Name)) + } + }}, TOTAL: {Hand: func(m *ice.Message, arg ...string) { stats := map[string]int{} if repos := kit.Select(m.Option(REPOS), arg, 0); repos == "" { @@ -482,11 +514,13 @@ func init() { }}, web.DREAM_CREATE: {Hand: func(m *ice.Message, arg ...string) { kit.If(m.Option(REPOS), func(p string) { + p = strings.Split(p, mdb.QS)[0] + kit.If(!strings.Contains(p, "://"), func() { p = web.UserHost(m) + "/x/" + p }) m.Cmd("", CLONE, ORIGIN, p, nfs.PATH, m.Option(cli.CMD_DIR), ice.Maps{cli.CMD_DIR: ""}) }) }}, code.INNER: {Hand: func(m *ice.Message, arg ...string) { _repos_inner(m, _repos_path, arg...) }}, - }, mdb.HashAction(mdb.SHORT, REPOS, mdb.FIELD, "time,repos,branch,commit,origin"), mdb.ClearOnExitHashAction()), Hand: func(m *ice.Message, arg ...string) { + }, gdb.EventsAction(web.DREAM_CREATE), mdb.HashAction(mdb.SHORT, REPOS, mdb.FIELD, "time,repos,branch,commit,origin"), mdb.ClearOnExitHashAction()), Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 { mdb.HashSelect(m, arg...).Sort(REPOS).Action(CLONE, PULL, PUSH, STATUS) } else if len(arg) == 1 { diff --git a/misc/git/service.go b/misc/git/service.go index 426dad73..0b818bf2 100644 --- a/misc/git/service.go +++ b/misc/git/service.go @@ -15,6 +15,7 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/cli" + "shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/lex" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" @@ -113,7 +114,7 @@ func init() { m.Warn(_service_repos(m, arg...), ice.ErrNotValid) }}}) Index.MergeCommands(ice.Commands{ - SERVICE: {Name: "service repos commit file auto", Help: "代码源", Actions: ice.MergeActions(ice.Actions{ + SERVICE: {Name: "service repos branch commit file auto", Help: "代码源", Actions: ice.MergeActions(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Cmd(nfs.DIR, ice.USR_LOCAL_REPOS, func(value ice.Maps) { _repos_insert(m, value[nfs.PATH]) }) }}, @@ -140,20 +141,29 @@ func init() { }}, TOKEN: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(TOKEN, cli.MAKE) }}, code.INNER: {Hand: func(m *ice.Message, arg ...string) { _repos_inner(m, _service_path, arg...) }}, - }, mdb.HashAction(mdb.SHORT, REPOS, mdb.FIELD, "time,repos,branch,commit"), mdb.ClearOnExitHashAction()), Hand: func(m *ice.Message, arg ...string) { + web.DREAM_INPUTS: {Hand: func(m *ice.Message, arg ...string) { + switch arg[0] { + case REPOS: + mdb.HashSelect(m).Sort(REPOS).Cut("repos,branch,commit,time") + } + }}, + }, gdb.EventsAction(web.DREAM_INPUTS), mdb.HashAction(mdb.SHORT, REPOS, mdb.FIELD, "time,repos,branch,commit"), mdb.ClearOnExitHashAction()), Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 { mdb.HashSelect(m, arg...).Sort(REPOS).Action(mdb.CREATE, TOKEN) m.Echo(strings.ReplaceAll(m.Cmdx("web.code.publish", ice.CONTEXTS), "app username", "dev username")) } else if len(arg) == 1 { + _repos_branch(m, _repos_open(m, arg[0])) + m.EchoScript(tcp.PublishLocalhost(m, kit.Split(web.MergeURL2(m, "/x/"+arg[0]), mdb.QS)[0])) + } else if len(arg) == 2 { repos := _repos_open(m, arg[0]) if branch, err := repos.Branch(arg[1]); !m.Warn(err) { _repos_log(m, branch, repos) } - } else if len(arg) == 2 { - if repos := _repos_open(m, arg[0]); arg[1] == INDEX { + } else if len(arg) == 3 { + if repos := _repos_open(m, arg[0]); arg[2] == INDEX { _repos_status(m, arg[0], repos) } else { - _repos_stats(m, repos, arg[1]) + _repos_stats(m, repos, arg[2]) } } else { m.Cmdy("", code.INNER, arg) diff --git a/misc/git/status.go b/misc/git/status.go index 89b8db54..c6d89f14 100644 --- a/misc/git/status.go +++ b/misc/git/status.go @@ -116,38 +116,27 @@ func init() { return } switch arg[0] { - case COMMENT: - ls := kit.Split(m.Option(nfs.FILE), " /") - m.Push(arg[0], kit.Join(kit.Slice(ls, -1), nfs.PS)) - m.Push(arg[0], kit.Join(kit.Slice(ls, -2), nfs.PS)) - m.Push(arg[0], m.Option(nfs.FILE)) - case VERSION: - m.Push(VERSION, _status_tag(m, m.Option(TAGS))) case aaa.EMAIL: m.Push(arg[0], _configs_get(m, USER_EMAIL), ice.Info.Make.Email) case aaa.USERNAME: m.Push(arg[0], kit.Select(m.Option(ice.MSG_USERNAME), _configs_get(m, USER_NAME)), ice.Info.Make.Username) + default: + m.Cmdy(REPOS, mdb.INPUTS, arg) } }}, - CONFIGS: {Name: "configs email username", Help: "配置", Hand: func(m *ice.Message, arg ...string) { - mdb.Config(m, aaa.USERNAME, m.Option(aaa.USERNAME)) - mdb.Config(m, aaa.EMAIL, m.Option(aaa.EMAIL)) - }}, INSTEADOF: {Name: "insteadof from* to", Help: "代理", Hand: func(m *ice.Message, arg ...string) { m.Cmd(CONFIGS, func(value ice.Maps) { kit.If(value[mdb.VALUE] == m.Option(nfs.FROM), func() { _configs_set(m, "--unset", value[mdb.NAME]) }) }) kit.If(m.Option(nfs.TO), func() { _git_cmd(m, CONFIG, "--global", "url."+m.Option(nfs.TO)+".insteadof", m.Option(nfs.FROM)) }) }}, + CONFIGS: {Name: "configs email username", Help: "配置", Hand: func(m *ice.Message, arg ...string) { + mdb.Config(m, aaa.USERNAME, m.Option(aaa.USERNAME)) + mdb.Config(m, aaa.EMAIL, m.Option(aaa.EMAIL)) + }}, OAUTH: {Help: "授权", Hand: func(m *ice.Message, arg ...string) { m.ProcessOpen(kit.MergeURL2(kit.Select(ice.Info.Make.Domain, _git_remote(m)), "/chat/cmd/web.code.git.token/gen/", tcp.HOST, m.Option(ice.MSG_USERWEB))) }}, - TAG: {Name: "tag version", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(REPOS, m.ActionKey(), arg) - }}, - COMMIT: {Name: "commit actions=add,opt,fix comment*=some", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(REPOS, m.ActionKey(), arg) - }}, web.DREAM_TABLES: {Hand: func(m *ice.Message, arg ...string) { if m.Option(mdb.TYPE) != web.WORKER { return @@ -164,7 +153,7 @@ func init() { } m.Push(mdb.TEXT, strings.Join(text, ", ")) }}, - }, gdb.EventAction(web.DREAM_TABLES), aaa.RoleAction(), mdb.ImportantDataAction()), Hand: func(m *ice.Message, arg ...string) { + }, gdb.EventAction(web.DREAM_TABLES), Prefix(REPOS), mdb.ImportantDataAction(), aaa.RoleAction()), Hand: func(m *ice.Message, arg ...string) { if len(arg) > 0 && arg[0] == ctx.ACTION { m.Cmdy(REPOS, arg) } else if config, err := config.LoadConfig(config.GlobalScope); err == nil && config.User.Email == "" && mdb.Config(m, aaa.EMAIL) == "" { diff --git a/misc/ssh/rsa.go b/misc/ssh/rsa.go index e5b29364..62f8c1a5 100644 --- a/misc/ssh/rsa.go +++ b/misc/ssh/rsa.go @@ -1,9 +1,12 @@ package ssh import ( + "crypto" "crypto/rand" "crypto/rsa" + "crypto/sha256" "crypto/x509" + "encoding/hex" "encoding/pem" "path" @@ -20,6 +23,8 @@ import ( const ( PUBLIC = "public" PRIVATE = "private" + VERIFY = "verify" + SIGN = "sign" ) const RSA = "rsa" @@ -60,6 +65,46 @@ func init() { PUBLIC, m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PUB))), )) }}, + SIGN: {Hand: func(m *ice.Message, arg ...string) { + if !nfs.Exists(m, "etc/id_rsa") { + if key, err := rsa.GenerateKey(rand.Reader, kit.Int("2048")); !m.Warn(err, ice.ErrNotValid) { + m.Cmd(nfs.SAVE, "etc/id_rsa", string(pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}))) + m.Cmd(nfs.SAVE, "etc/id_rsa.pub", string(pem.EncodeToMemory(&pem.Block{Type: "RSA PUBLIC KEY", Bytes: x509.MarshalPKCS1PublicKey(key.Public().(*rsa.PublicKey))}))) + } + } + block, _ := pem.Decode([]byte(m.Cmdx(nfs.CAT, "etc/id_rsa"))) + key, err := x509.ParsePKCS1PrivateKey(block.Bytes) + if m.Warn(err) { + return + } + hash := sha256.New() + if _, err := hash.Write([]byte(arg[0])); m.Warn(err) { + return + } + signature, err := rsa.SignPSS(rand.Reader, key, crypto.SHA256, hash.Sum(nil), nil) + if m.Warn(err) { + return + } + m.Echo(hex.EncodeToString(signature)) + }}, + VERIFY: {Hand: func(m *ice.Message, arg ...string) { + block, _ := pem.Decode([]byte(m.Cmdx(nfs.CAT, "etc/id_rsa.pub"))) + pub, err := x509.ParsePKCS1PublicKey(block.Bytes) + if m.Warn(err) { + return + } + signature, err := hex.DecodeString(arg[1]) + if m.Warn(err) { + return + } + hash := sha256.New() + if _, err := hash.Write([]byte(arg[0])); m.Warn(err) { + return + } + if !m.Warn(rsa.VerifyPSS(pub, crypto.SHA256, hash.Sum(nil), signature, nil)) { + m.Echo(ice.OK) + } + }}, }, mdb.HashAction(mdb.SHORT, PRIVATE, mdb.FIELD, "time,hash,title,public,private")), Hand: func(m *ice.Message, arg ...string) { if mdb.HashSelect(m, arg...).PushAction(mdb.EXPORT, mdb.REMOVE); len(arg) == 0 { m.Action(mdb.CREATE, mdb.IMPORT)