From 3f24b4da2e8f4a5acd8be199ea2122d7ec828ed4 Mon Sep 17 00:00:00 2001 From: Wlynxg Date: Mon, 13 Jan 2025 09:26:59 +0800 Subject: [PATCH 1/4] feat(os/gcmd): add default value display for an argument (#4083) --- os/gcmd/gcmd_command.go | 11 ++++++----- os/gcmd/gcmd_command_help.go | 3 +++ os/gcmd/gcmd_command_object.go | 3 +++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/os/gcmd/gcmd_command.go b/os/gcmd/gcmd_command.go index ce05820602d..80c824da3a8 100644 --- a/os/gcmd/gcmd_command.go +++ b/os/gcmd/gcmd_command.go @@ -46,11 +46,12 @@ type FuncWithValue func(ctx context.Context, parser *Parser) (out interface{}, e // Argument is the command value that are used by certain command. type Argument struct { - Name string // Option name. - Short string // Option short. - Brief string // Brief info about this Option, which is used in help info. - IsArg bool // IsArg marks this argument taking value from command line argument instead of option. - Orphan bool // Whether this Option having or having no value bound to it. + Name string // Option name. + Short string // Option short. + Default string // Option default value. + Brief string // Brief info about this Option, which is used in help info. + IsArg bool // IsArg marks this argument taking value from command line argument instead of option. + Orphan bool // Whether this Option having or having no value bound to it. } var ( diff --git a/os/gcmd/gcmd_command_help.go b/os/gcmd/gcmd_command_help.go index ab43641e931..c9aa8598560 100644 --- a/os/gcmd/gcmd_command_help.go +++ b/os/gcmd/gcmd_command_help.go @@ -156,6 +156,9 @@ func (c *Command) PrintTo(writer io.Writer) { spaceLength = maxSpaceLength - len(nameStr) wordwrapPrefix = gstr.Repeat(" ", len(prefix+nameStr)+spaceLength+4) ) + if arg.Default != "" { + brief = fmt.Sprintf("%s (default: \"%s\")", brief, arg.Default) + } c.printLineBrief(printLineBriefInput{ Buffer: buffer, Name: nameStr, diff --git a/os/gcmd/gcmd_command_object.go b/os/gcmd/gcmd_command_object.go index c7e49b54714..f98820591fe 100644 --- a/os/gcmd/gcmd_command_object.go +++ b/os/gcmd/gcmd_command_object.go @@ -378,6 +378,9 @@ func newArgumentsFromInput(object interface{}) (args []Argument, err error) { if arg.Brief == "" { arg.Brief = field.TagDescription() } + if arg.Default == "" { + arg.Default = field.TagDefault() + } if v, ok := metaData[gtag.Arg]; ok { arg.IsArg = gconv.Bool(v) } From e0f734851ef548359b77218ac4a2e05f9a981ef4 Mon Sep 17 00:00:00 2001 From: Wlynxg Date: Tue, 14 Jan 2025 09:28:19 +0800 Subject: [PATCH 2/4] fix(net/ghttp): `MiddlewareHandlerResponse` writes additional information after custom response wrote (#4109) --- .../ghttp_middleware_handler_response.go | 2 +- net/ghttp/ghttp_z_unit_issue_test.go | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/net/ghttp/ghttp_middleware_handler_response.go b/net/ghttp/ghttp_middleware_handler_response.go index cebff3889d3..7eb50b2d127 100644 --- a/net/ghttp/ghttp_middleware_handler_response.go +++ b/net/ghttp/ghttp_middleware_handler_response.go @@ -37,7 +37,7 @@ func MiddlewareHandlerResponse(r *Request) { r.Middleware.Next() // There's custom buffer content, it then exits current handler. - if r.Response.BufferLength() > 0 { + if r.Response.BufferLength() > 0 || r.Response.Writer.BytesWritten() > 0 { return } diff --git a/net/ghttp/ghttp_z_unit_issue_test.go b/net/ghttp/ghttp_z_unit_issue_test.go index 080597d0d52..e14a38eed46 100644 --- a/net/ghttp/ghttp_z_unit_issue_test.go +++ b/net/ghttp/ghttp_z_unit_issue_test.go @@ -9,6 +9,7 @@ package ghttp_test import ( "context" "fmt" + "net/http" "testing" "time" @@ -630,3 +631,28 @@ func Test_Issue4047(t *testing.T) { t.Assert(s.Logger(), nil) }) } + +// https://github.com/gogf/gf/issues/4108 +func Test_Issue4108(t *testing.T) { + s := g.Server(guid.S()) + s.Group("/", func(group *ghttp.RouterGroup) { + group.Middleware(ghttp.MiddlewareHandlerResponse) + group.GET("/", func(r *ghttp.Request) { + r.Response.Writer.Write([]byte("hello")) + }) + }) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + time.Sleep(100 * time.Millisecond) + + gtest.C(t, func(t *gtest.T) { + client := g.Client() + client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) + + rsp, err := client.Get(ctx, "/") + t.AssertNil(err) + t.Assert(rsp.StatusCode, http.StatusOK) + t.Assert(rsp.ReadAllString(), "hello") + }) +} From 99f0fb14a102a00736798607fdf355e21ea30711 Mon Sep 17 00:00:00 2001 From: Wlynxg Date: Wed, 22 Jan 2025 09:28:06 +0800 Subject: [PATCH 3/4] fix(net/ghttp): BufferWriter.Flush writes additional information after custom response wrote (#4116) --- net/ghttp/ghttp_z_unit_issue_test.go | 22 +++++++++++++++++++ .../response/response_buffer_writer.go | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/net/ghttp/ghttp_z_unit_issue_test.go b/net/ghttp/ghttp_z_unit_issue_test.go index e14a38eed46..f8b2069e2ec 100644 --- a/net/ghttp/ghttp_z_unit_issue_test.go +++ b/net/ghttp/ghttp_z_unit_issue_test.go @@ -656,3 +656,25 @@ func Test_Issue4108(t *testing.T) { t.Assert(rsp.ReadAllString(), "hello") }) } + +// https://github.com/gogf/gf/issues/4115 +func Test_Issue4115(t *testing.T) { + s := g.Server(guid.S()) + s.Use(func(r *ghttp.Request) { + r.Response.Writer.Write([]byte("hello")) + }) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + time.Sleep(100 * time.Millisecond) + + gtest.C(t, func(t *gtest.T) { + client := g.Client() + client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) + + rsp, err := client.Get(ctx, "/") + t.AssertNil(err) + t.Assert(rsp.StatusCode, http.StatusOK) + t.Assert(rsp.ReadAllString(), "hello") + }) +} diff --git a/net/ghttp/internal/response/response_buffer_writer.go b/net/ghttp/internal/response/response_buffer_writer.go index f1f65c88e19..8b334d79049 100644 --- a/net/ghttp/internal/response/response_buffer_writer.go +++ b/net/ghttp/internal/response/response_buffer_writer.go @@ -82,7 +82,7 @@ func (w *BufferWriter) Flush() { w.Writer.WriteHeader(w.Status) } // Default status text output. - if w.Status != http.StatusOK && w.buffer.Len() == 0 { + if w.Status != http.StatusOK && w.buffer.Len() == 0 && w.Writer.BytesWritten() == 0 { w.buffer.WriteString(http.StatusText(w.Status)) } if w.buffer.Len() > 0 { From e12768207e173c9734a6a58ce05c05d0a860ac4b Mon Sep 17 00:00:00 2001 From: wanna Date: Wed, 22 Jan 2025 19:22:36 +0800 Subject: [PATCH 4/4] feat(cmd/gf): beautify progress bar of cli binary downloading for command `gf up` (#4094) --- cmd/gf/go.mod | 3 + cmd/gf/go.sum | 10 +++ .../utility/utils/utils_http_download.go | 62 ++----------------- 3 files changed, 18 insertions(+), 57 deletions(-) diff --git a/cmd/gf/go.mod b/cmd/gf/go.mod index e2d19e73074..ae17a9e1090 100644 --- a/cmd/gf/go.mod +++ b/cmd/gf/go.mod @@ -12,6 +12,7 @@ require ( github.com/gogf/gf/v2 v2.8.3 github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f github.com/olekukonko/tablewriter v0.0.5 + github.com/schollz/progressbar/v3 v3.15.0 golang.org/x/mod v0.17.0 golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d ) @@ -40,6 +41,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/microsoft/go-mssqldb v1.7.1 // indirect + github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/paulmach/orb v0.7.1 // indirect github.com/pierrec/lz4/v4 v4.1.14 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect @@ -54,6 +56,7 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.28.0 // indirect + golang.org/x/term v0.27.0 // indirect golang.org/x/text v0.21.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/libc v1.22.5 // indirect diff --git a/cmd/gf/go.sum b/cmd/gf/go.sum index ad3b4a1875d..e29244f933b 100644 --- a/cmd/gf/go.sum +++ b/cmd/gf/go.sum @@ -18,6 +18,7 @@ github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= @@ -76,6 +77,7 @@ github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= @@ -95,6 +97,8 @@ github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/microsoft/go-mssqldb v1.7.1 h1:KU/g8aWeM3Hx7IMOFpiwYiUkU+9zeISb4+tx3ScVfsM= github.com/microsoft/go-mssqldb v1.7.1/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA= +github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= +github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615/go.mod h1:Ad7oeElCZqA1Ufj0U9/liOF4BtVepxRcTvr2ey7zTvM= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= @@ -113,6 +117,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qq github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/schollz/progressbar/v3 v3.15.0 h1:cNZmcNiVyea6oofBTg80ZhVXxf3wG/JoAhqCCwopkQo= +github.com/schollz/progressbar/v3 v3.15.0/go.mod h1:ncBdc++eweU0dQoeZJ3loXoAc+bjaallHRIm8pVVeQM= github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= @@ -173,9 +179,13 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= diff --git a/cmd/gf/internal/utility/utils/utils_http_download.go b/cmd/gf/internal/utility/utils/utils_http_download.go index a0654d0c641..0b8bb6eb539 100644 --- a/cmd/gf/internal/utility/utils/utils_http_download.go +++ b/cmd/gf/internal/utility/utils/utils_http_download.go @@ -7,13 +7,13 @@ package utils import ( - "fmt" "io" "net/http" "os" - "strconv" "time" + "github.com/schollz/progressbar/v3" + "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog" @@ -34,26 +34,16 @@ func HTTPDownloadFileWithPercent(url string, localSaveFilePath string) error { } defer headResp.Body.Close() - size, err := strconv.Atoi(headResp.Header.Get("Content-Length")) - if err != nil { - return gerror.Wrap(err, "retrieve Content-Length failed") - } - doneCh := make(chan int64) - - go doPrintDownloadPercent(doneCh, localSaveFilePath, int64(size)) - resp, err := http.Get(url) if err != nil { return gerror.Wrapf(err, `download "%s" to "%s" failed`, url, localSaveFilePath) } defer resp.Body.Close() - wroteBytesCount, err := io.Copy(out, resp.Body) - if err != nil { - return gerror.Wrapf(err, `download "%s" to "%s" failed`, url, localSaveFilePath) - } + bar := progressbar.NewOptions(int(resp.ContentLength), progressbar.OptionShowBytes(true), progressbar.OptionShowCount()) + writer := io.MultiWriter(out, bar) + _, err = io.Copy(writer, resp.Body) - doneCh <- wroteBytesCount elapsed := time.Since(start) if elapsed > time.Minute { mlog.Printf(`download completed in %.0fm`, float64(elapsed)/float64(time.Minute)) @@ -63,45 +53,3 @@ func HTTPDownloadFileWithPercent(url string, localSaveFilePath string) error { return nil } - -func doPrintDownloadPercent(doneCh chan int64, localSaveFilePath string, total int64) { - var ( - stop = false - lastPercentFmt string - ) - file, err := os.Open(localSaveFilePath) - if err != nil { - mlog.Fatal(err) - } - defer file.Close() - - for { - select { - case <-doneCh: - stop = true - - default: - fi, err := file.Stat() - if err != nil { - mlog.Fatal(err) - } - size := fi.Size() - if size == 0 { - size = 1 - } - var ( - percent = float64(size) / float64(total) * 100 - percentFmt = fmt.Sprintf(`%.0f`, percent) + "%" - ) - if lastPercentFmt != percentFmt { - lastPercentFmt = percentFmt - mlog.Print(percentFmt) - } - } - - if stop { - break - } - time.Sleep(time.Second) - } -}