diff --git a/go.mod b/go.mod index 2dae8084..fa2b1652 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/go-playground/validator/v10 v10.24.0 github.com/gregdel/pushover v1.3.1 github.com/hashicorp/nomad/api v0.0.0-20231213195942-64e3dca9274b // v1.7.2 - github.com/jedib0t/go-pretty/v6 v6.6.5 + github.com/jedib0t/go-pretty/v6 v6.6.7 github.com/matcornic/hermes/v2 v2.1.0 github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 github.com/microcosm-cc/bluemonday v1.0.27 @@ -72,7 +72,7 @@ require ( github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/felixge/fgprof v0.9.3 // indirect + github.com/felixge/fgprof v0.9.5 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect diff --git a/go.sum b/go.sum index 80388253..a7b81b9d 100644 --- a/go.sum +++ b/go.sum @@ -44,9 +44,15 @@ github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqy github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= +github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= +github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= @@ -96,8 +102,9 @@ github.com/eclipse/paho.mqtt.golang v1.5.0 h1:EH+bUVJNgttidWFkLLVKaQPGmkTUfQQqjO github.com/eclipse/paho.mqtt.golang v1.5.0/go.mod h1:du/2qNQVqJf/Sqs4MEL77kR8QTqANF7XU7Fk0aOTAgk= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= +github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY= +github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= @@ -127,6 +134,9 @@ github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -141,6 +151,7 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= +github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -178,12 +189,13 @@ github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4Dvx github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0= github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0 h1:xqgexXAGQgY3HAjNPSaCqn5Aahbo5TKsmhp8VRfr1iQ= github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= -github.com/jedib0t/go-pretty/v6 v6.6.5 h1:9PgMJOVBedpgYLI56jQRJYqngxYAAzfEUua+3NgSqAo= -github.com/jedib0t/go-pretty/v6 v6.6.5/go.mod h1:Uq/HrbhuFty5WSVNfjpQQe47x16RwVGXIveNGEyGtHs= +github.com/jedib0t/go-pretty/v6 v6.6.7 h1:m+LbHpm0aIAPLzLbMfn8dc3Ht8MW7lsSO4MPItz/Uuo= +github.com/jedib0t/go-pretty/v6 v6.6.7/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -203,6 +215,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -266,6 +279,7 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/panjf2000/ants/v2 v2.11.0 h1:sHrqEwTBQTQ2w6PMvbMfvBtVUuhsaYPzUmAYDLYmJPg= github.com/panjf2000/ants/v2 v2.11.0/go.mod h1:V9HhTupTWxcaRmIglJvGwvzqXUTnIZW9uO6q4hAfApw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -407,6 +421,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/vendor/github.com/felixge/fgprof/README.md b/vendor/github.com/felixge/fgprof/README.md index 15b16794..6f9f066b 100644 --- a/vendor/github.com/felixge/fgprof/README.md +++ b/vendor/github.com/felixge/fgprof/README.md @@ -1,6 +1,7 @@ [![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go)](https://pkg.go.dev/github.com/felixge/fgprof) ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/felixge/fgprof/Go) ![GitHub](https://img.shields.io/github/license/felixge/fgprof) +[![go-recipes](https://raw.githubusercontent.com/nikolaydubina/go-recipes/main/badge.svg?raw=true)](https://github.com/nikolaydubina/go-recipes) # :rocket: fgprof - The Full Go Profiler diff --git a/vendor/github.com/felixge/fgprof/fgprof.go b/vendor/github.com/felixge/fgprof/fgprof.go index 18f7d6f5..459787b6 100644 --- a/vendor/github.com/felixge/fgprof/fgprof.go +++ b/vendor/github.com/felixge/fgprof/fgprof.go @@ -6,6 +6,7 @@ package fgprof import ( "fmt" "io" + "math" "runtime" "sort" "strings" @@ -37,16 +38,19 @@ func Start(w io.Writer, format Format) func() error { const hz = 99 ticker := time.NewTicker(time.Second / hz) stopCh := make(chan struct{}) - prof := &profiler{} profile := newWallclockProfile() + var sampleCount int64 + go func() { defer ticker.Stop() for { select { case <-ticker.C: + sampleCount++ + stacks := prof.GoroutineProfile() profile.Add(stacks) case <-stopCh: @@ -59,7 +63,14 @@ func Start(w io.Writer, format Format) func() error { stopCh <- struct{}{} endTime := time.Now() profile.Ignore(prof.SelfFrames()...) - return profile.Export(w, format, hz, startTime, endTime) + + // Compute actual sample rate in case, due to performance issues, we + // were not actually able to sample at the given hz. Converting + // everything to float avoids integers being rounded in the wrong + // direction and improves the correctness of times in profiles. + duration := endTime.Sub(startTime) + actualHz := float64(sampleCount) / (float64(duration) / 1e9) + return profile.Export(w, format, int(math.Round(actualHz)), startTime, endTime) } } @@ -70,6 +81,11 @@ type profiler struct { selfFrame *runtime.Frame } +// nullTerminationWorkaround deals with a regression in go1.23, see: +// - https://github.com/felixge/fgprof/issues/33 +// - https://go-review.googlesource.com/c/go/+/609815 +var nullTerminationWorkaround = runtime.Version() == "go1.23.0" + // GoroutineProfile returns the stacks of all goroutines currently managed by // the scheduler. This includes both goroutines that are currently running // (On-CPU), as well as waiting (Off-CPU). @@ -96,6 +112,11 @@ func (p *profiler) GoroutineProfile() []runtime.StackRecord { // p.stacks dynamically as well, but let's not over-engineer this until we // understand those cases better. for { + if nullTerminationWorkaround { + for i := range p.stacks { + p.stacks[i].Stack0 = [32]uintptr{} + } + } n, ok := runtime.GoroutineProfile(p.stacks) if !ok { p.stacks = make([]runtime.StackRecord, int(float64(n)*1.1)) diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/config.go b/vendor/github.com/jedib0t/go-pretty/v6/table/config.go index fb96d708..c36124a2 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/config.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/config.go @@ -25,8 +25,8 @@ type ColumnConfig struct { // AutoMerge merges cells with similar values and prevents separators from // being drawn. Caveats: // * VAlign is applied on the individual cell and not on the merged cell - // * Does not work in CSV/HTML/Markdown render modes // * Does not work well with horizontal auto-merge (RowConfig.AutoMerge) + // * Does not work in CSV/Markdown render modes // // Works best when: // * Style().Options.SeparateRows == true @@ -87,8 +87,8 @@ type RowConfig struct { // being drawn. Caveats: // * Align is overridden to text.AlignCenter on the merged cell (unless set // by AutoMergeAlign value below) - // * Does not work in CSV/HTML/Markdown render modes // * Does not work well with vertical auto-merge (ColumnConfig.AutoMerge) + // * Does not work in CSV/Markdown render modes AutoMerge bool // Alignment to use on a merge (defaults to text.AlignCenter) diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/render.go b/vendor/github.com/jedib0t/go-pretty/v6/table/render.go index 2fd759e6..4ef68f99 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/render.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/render.go @@ -67,7 +67,7 @@ func (t *Table) renderColumn(out *strings.Builder, row rowStr, colIdx int, maxCo } // extract the text, convert-case if not-empty and align horizontally - mergeVertically := t.shouldMergeCellsVertically(colIdx, hint) + mergeVertically := t.shouldMergeCellsVerticallyAbove(colIdx, hint) var colStr string if mergeVertically { // leave colStr empty; align will expand the column as necessary diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/render_html.go b/vendor/github.com/jedib0t/go-pretty/v6/table/render_html.go index decf4fa0..729f95ee 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/render_html.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/render_html.go @@ -159,6 +159,10 @@ func (t *Table) htmlRenderRow(out *strings.Builder, row rowStr, hint renderHint) if colIdx == 0 && t.autoIndex { t.htmlRenderColumnAutoIndex(out, hint) } + // auto-merged columns should be skipped + if t.shouldMergeCellsVerticallyAbove(colIdx, hint) { + continue + } align := t.getAlign(colIdx, hint) rowConfig := t.getRowConfig(hint) @@ -184,6 +188,9 @@ func (t *Table) htmlRenderRow(out *strings.Builder, row rowStr, hint renderHint) if extraColumnsRendered > 0 { out.WriteString(" colspan=") out.WriteString(fmt.Sprint(extraColumnsRendered + 1)) + } else if rowSpan := t.shouldMergeCellsVerticallyBelow(colIdx, hint); rowSpan > 1 { + out.WriteString(" rowspan=") + out.WriteString(fmt.Sprint(rowSpan)) } out.WriteString(">") if len(colStr) == 0 { @@ -222,6 +229,7 @@ func (t *Table) htmlRenderRows(out *strings.Builder, rows []rowStr, hint renderH t.htmlRenderRow(out, row, hint) shouldRenderTagClose = true } + t.firstRowOfPage = false } if shouldRenderTagClose { out.WriteString(" 0 && maxColWidth < longestLineLen { longestLineLen = maxColWidth } - mergedColumnsLength := mci.mergedLength(colIdx, t.maxColumnLengths) - if longestLineLen > mergedColumnsLength { - if mergedColumnsLength > 0 { - t.extractMaxColumnLengthsFromRowForMergedColumns(colIdx, longestLineLen, mci) - } else { - t.maxColumnLengths[colIdx] = longestLineLen + + if mergeEndIndex, ok := mci[colIdx]; ok { + startIndexMap := t.maxMergedColumnLengths[mergeEndIndex] + if startIndexMap == nil { + startIndexMap = make(map[int]int) + t.maxMergedColumnLengths[mergeEndIndex] = startIndexMap } - } else if maxColWidth == 0 && longestLineLen > t.maxColumnLengths[colIdx] { + if longestLineLen > startIndexMap[colIdx] { + startIndexMap[colIdx] = longestLineLen + } + colIdx = mergeEndIndex + } else if longestLineLen > t.maxColumnLengths[colIdx] { t.maxColumnLengths[colIdx] = longestLineLen } } } -func (t *Table) extractMaxColumnLengthsFromRowForMergedColumns(colIdx int, mergedColumnLength int, mci mergedColumnIndices) { - numMergedColumns := mci.len(colIdx) - mergedColumnLength -= (numMergedColumns - 1) * text.StringWidthWithoutEscSequences(t.style.Box.MiddleSeparator) - maxLengthSplitAcrossColumns := mergedColumnLength / numMergedColumns - if maxLengthSplitAcrossColumns > t.maxColumnLengths[colIdx] { - t.maxColumnLengths[colIdx] = maxLengthSplitAcrossColumns - } - for otherColIdx := range mci[colIdx] { - if maxLengthSplitAcrossColumns > t.maxColumnLengths[otherColIdx] { - t.maxColumnLengths[otherColIdx] = maxLengthSplitAcrossColumns +// reBalanceMaxMergedColumnLengths tries to re-balance the merged column lengths +// across all columns. It does this from the lowest end index to the highest, +// and within that set from the highest start index to the lowest. It +// distributes the length across the columns not already exceeding the average. +func (t *Table) reBalanceMaxMergedColumnLengths() { + endIndexKeys, startIndexKeysMap := getSortedKeys(t.maxMergedColumnLengths) + middleSepLen := text.StringWidthWithoutEscSequences(t.style.Box.MiddleSeparator) + for _, endIndexKey := range endIndexKeys { + startIndexKeys := startIndexKeysMap[endIndexKey] + for idx := len(startIndexKeys) - 1; idx >= 0; idx-- { + startIndexKey := startIndexKeys[idx] + columnBalanceMap := map[int]struct{}{} + for index := startIndexKey; index <= endIndexKey; index++ { + columnBalanceMap[index] = struct{}{} + } + mergedColumnLength := t.maxMergedColumnLengths[endIndexKey][startIndexKey] - + ((len(columnBalanceMap) - 1) * middleSepLen) + + // keep reducing the set of columns until the remainder are the ones less than + // the average of the remaining length (total merged length - all lengths > average) + for { + if mergedColumnLength <= 0 { // already exceeded the merged length + columnBalanceMap = map[int]struct{}{} + break + } + numMergedColumns := len(columnBalanceMap) + maxLengthSplitAcrossColumns := mergedColumnLength / numMergedColumns + mapReduced := false + for mergedColumn := range columnBalanceMap { + maxColumnLength := t.maxColumnLengths[mergedColumn] + if maxColumnLength >= maxLengthSplitAcrossColumns { + mapReduced = true + mergedColumnLength -= maxColumnLength + delete(columnBalanceMap, mergedColumn) + } + } + if !mapReduced { + break + } + } + + // act on any remaining columns that need balancing + if len(columnBalanceMap) > 0 { + // remove the max column sizes from the remaining amount to balance, then + // share out the remainder amongst the columns. + numRebalancedColumns := len(columnBalanceMap) + balanceColumns := make([]int, 0, numRebalancedColumns) + for balanceColumn := range columnBalanceMap { + mergedColumnLength -= t.maxColumnLengths[balanceColumn] + balanceColumns = append(balanceColumns, balanceColumn) + } + // pad out the columns one by one + sort.Ints(balanceColumns) + columnLengthRemaining := mergedColumnLength + columnsRemaining := numRebalancedColumns + for index := 0; index < numRebalancedColumns; index++ { + balancedSpace := columnLengthRemaining / columnsRemaining + balanceColumn := balanceColumns[index] + t.maxColumnLengths[balanceColumn] += balancedSpace + columnLengthRemaining -= balancedSpace + columnsRemaining-- + } + } } } } @@ -136,6 +195,7 @@ func (t *Table) initForRenderColumnConfigs() { func (t *Table) initForRenderColumnLengths() { t.maxColumnLengths = make([]int, t.numColumns) + t.maxMergedColumnLengths = make(map[int]map[int]int) t.extractMaxColumnLengths(t.rowsHeader, renderHint{isHeaderRow: true}) t.extractMaxColumnLengths(t.rows, renderHint{}) t.extractMaxColumnLengths(t.rowsFooter, renderHint{isFooterRow: true}) @@ -147,6 +207,7 @@ func (t *Table) initForRenderColumnLengths() { t.maxColumnLengths[colIdx] = minWidth } } + t.reBalanceMaxMergedColumnLengths() } func (t *Table) initForRenderHideColumns() { diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/render_tsv.go b/vendor/github.com/jedib0t/go-pretty/v6/table/render_tsv.go index bb739750..67f1e7f7 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/render_tsv.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/render_tsv.go @@ -50,7 +50,8 @@ func (t *Table) tsvRenderRow(out *strings.Builder, row rowStr, hint renderHint) } if strings.ContainsAny(col, "\t\n\"") || strings.Contains(col, " ") { - out.WriteString(fmt.Sprintf("\"%s\"", t.tsvFixDoubleQuotes(col))) + col = strings.ReplaceAll(col, "\"", "\"\"") // fix double-quotes + out.WriteString(fmt.Sprintf("\"%s\"", col)) } else { out.WriteString(col) } @@ -61,10 +62,6 @@ func (t *Table) tsvRenderRow(out *strings.Builder, row rowStr, hint renderHint) } } -func (t *Table) tsvFixDoubleQuotes(str string) string { - return strings.Replace(str, "\"", "\"\"", -1) -} - func (t *Table) tsvRenderRows(out *strings.Builder, rows []rowStr, hint renderHint) { for idx, row := range rows { hint.rowNumber = idx + 1 diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/table.go b/vendor/github.com/jedib0t/go-pretty/v6/table/table.go index ea2fae68..191dd771 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/table.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/table.go @@ -36,6 +36,9 @@ type Table struct { indexColumn int // maxColumnLengths stores the length of the longest line in each column maxColumnLengths []int + // maxMergedColumnLengths stores the longest lengths for merged columns + // endIndex -> startIndex -> maxMergedLength + maxMergedColumnLengths map[int]map[int]int // maxRowLength stores the length of the longest row maxRowLength int // numColumns stores the (max.) number of columns seen @@ -431,7 +434,7 @@ func (t *Table) getBorderLeft(hint renderHint) string { } else if hint.isSeparatorRow { if t.autoIndex && hint.isHeaderOrFooterSeparator() { border = t.style.Box.Left - } else if !t.autoIndex && t.shouldMergeCellsVertically(0, hint) { + } else if !t.autoIndex && t.shouldMergeCellsVerticallyAbove(0, hint) { border = t.style.Box.Left } else { border = t.style.Box.LeftSeparator @@ -451,7 +454,7 @@ func (t *Table) getBorderRight(hint renderHint) string { } else if hint.isBorderBottom { border = t.style.Box.BottomRight } else if hint.isSeparatorRow { - if t.shouldMergeCellsVertically(t.numColumns-1, hint) { + if t.shouldMergeCellsVerticallyAbove(t.numColumns-1, hint) { border = t.style.Box.Right } else { border = t.style.Box.RightSeparator @@ -522,12 +525,12 @@ func (t *Table) getColumnSeparator(row rowStr, colIdx int, hint renderHint) stri } func (t *Table) getColumnSeparatorNonBorder(mergeCellsAbove bool, mergeCellsBelow bool, colIdx int, hint renderHint) string { - mergeNextCol := t.shouldMergeCellsVertically(colIdx, hint) + mergeNextCol := t.shouldMergeCellsVerticallyAbove(colIdx, hint) if hint.isAutoIndexColumn { return t.getColumnSeparatorNonBorderAutoIndex(mergeNextCol, hint) } - mergeCurrCol := t.shouldMergeCellsVertically(colIdx-1, hint) + mergeCurrCol := t.shouldMergeCellsVerticallyAbove(colIdx-1, hint) return t.getColumnSeparatorNonBorderNonAutoIndex(mergeCellsAbove, mergeCellsBelow, mergeCurrCol, mergeNextCol) } @@ -619,19 +622,19 @@ func (t *Table) getMergedColumnIndices(row rowStr, hint renderHint) mergedColumn mci := make(mergedColumnIndices) for colIdx := 0; colIdx < t.numColumns-1; colIdx++ { - // look backward - for otherColIdx := colIdx - 1; colIdx >= 0 && otherColIdx >= 0; otherColIdx-- { - if row[colIdx] != row[otherColIdx] { + for otherColIdx := colIdx + 1; otherColIdx < len(row); otherColIdx++ { + colsEqual := row[colIdx] == row[otherColIdx] + if !colsEqual { + lastEqual := otherColIdx - 1 + if colIdx != lastEqual { + mci[colIdx] = lastEqual + colIdx = lastEqual + } break + } else if colsEqual && otherColIdx == len(row)-1 { + mci[colIdx] = otherColIdx + colIdx = otherColIdx } - mci.safeAppend(colIdx, otherColIdx) - } - // look forward - for otherColIdx := colIdx + 1; colIdx < len(row) && otherColIdx < len(row); otherColIdx++ { - if row[colIdx] != row[otherColIdx] { - break - } - mci.safeAppend(colIdx, otherColIdx) } } return mci @@ -836,7 +839,7 @@ func (t *Table) shouldMergeCellsHorizontallyBelow(row rowStr, colIdx int, hint r return false } -func (t *Table) shouldMergeCellsVertically(colIdx int, hint renderHint) bool { +func (t *Table) shouldMergeCellsVerticallyAbove(colIdx int, hint renderHint) bool { if !t.firstRowOfPage && t.columnConfigMap[colIdx].AutoMerge && colIdx < t.numColumns { if hint.isSeparatorRow { rowPrev := t.getRow(hint.rowNumber-1, hint) @@ -855,6 +858,23 @@ func (t *Table) shouldMergeCellsVertically(colIdx int, hint renderHint) bool { return false } +func (t *Table) shouldMergeCellsVerticallyBelow(colIdx int, hint renderHint) int { + numRowsToMerge := 0 + if t.columnConfigMap[colIdx].AutoMerge && colIdx < t.numColumns { + numRowsToMerge = 1 + rowCurr := t.getRow(hint.rowNumber-1, hint) + for rowIdx := hint.rowNumber; rowIdx < len(t.rows); rowIdx++ { + rowNext := t.getRow(rowIdx, hint) + if colIdx < len(rowCurr) && colIdx < len(rowNext) && rowNext[colIdx] == rowCurr[colIdx] { + numRowsToMerge++ + } else { + break + } + } + } + return numRowsToMerge +} + func (t *Table) shouldSeparateRows(rowIdx int, numRows int) bool { // not asked to separate rows and no manually added separator if !t.style.Options.SeparateRows && !t.separators[rowIdx] { diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/util.go b/vendor/github.com/jedib0t/go-pretty/v6/table/util.go index 6b7a6585..4636e881 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/util.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/util.go @@ -2,6 +2,7 @@ package table import ( "reflect" + "sort" ) // AutoIndexColumnID returns a unique Column ID/Name for the given Column Number. @@ -40,33 +41,7 @@ func isNumber(x interface{}) bool { return false } -type mergedColumnIndices map[int]map[int]bool - -func (m mergedColumnIndices) mergedLength(colIdx int, maxColumnLengths []int) int { - mergedLength := maxColumnLengths[colIdx] - for otherColIdx := range m[colIdx] { - mergedLength += maxColumnLengths[otherColIdx] - } - return mergedLength -} - -func (m mergedColumnIndices) len(colIdx int) int { - return len(m[colIdx]) + 1 -} - -func (m mergedColumnIndices) safeAppend(colIdx, otherColIdx int) { - // map - if m[colIdx] == nil { - m[colIdx] = make(map[int]bool) - } - m[colIdx][otherColIdx] = true - - // reverse map - if m[otherColIdx] == nil { - m[otherColIdx] = make(map[int]bool) - } - m[otherColIdx][colIdx] = true -} +type mergedColumnIndices map[int]int func objAsSlice(in interface{}) []interface{} { var out []interface{} @@ -110,3 +85,19 @@ func objIsSlice(in interface{}) bool { k := reflect.TypeOf(in).Kind() return k == reflect.Slice || k == reflect.Array } + +func getSortedKeys(input map[int]map[int]int) ([]int, map[int][]int) { + keys := make([]int, 0, len(input)) + subkeysMap := make(map[int][]int) + for key, subMap := range input { + keys = append(keys, key) + subkeys := make([]int, 0, len(subMap)) + for subkey := range subMap { + subkeys = append(subkeys, subkey) + } + sort.Ints(subkeys) + subkeysMap[key] = subkeys + } + sort.Ints(keys) + return keys, subkeysMap +} diff --git a/vendor/github.com/jedib0t/go-pretty/v6/text/color.go b/vendor/github.com/jedib0t/go-pretty/v6/text/color.go index f42dfb38..4154111f 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/text/color.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/text/color.go @@ -2,13 +2,14 @@ package text import ( "fmt" + "os" "sort" "strconv" "strings" "sync" ) -var colorsEnabled = areANSICodesSupported() +var colorsEnabled = areColorsOnInTheEnv() && areANSICodesSupported() // DisableColors (forcefully) disables color coding globally. func DisableColors() { @@ -20,6 +21,15 @@ func EnableColors() { colorsEnabled = true } +// areColorsOnInTheEnv returns true is colors are not disable using +// well known environment variables. +func areColorsOnInTheEnv() bool { + if os.Getenv("FORCE_COLOR") == "1" { + return true + } + return os.Getenv("NO_COLOR") == "" || os.Getenv("NO_COLOR") == "0" +} + // The logic here is inspired from github.com/fatih/color; the following is // the bare minimum logic required to print Colored to the console. // The differences: diff --git a/vendor/modules.txt b/vendor/modules.txt index 9b13bdf6..a5379af7 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -189,7 +189,7 @@ github.com/eclipse/paho.mqtt.golang/packets ## explicit; go 1.13 github.com/emicklei/go-restful/v3 github.com/emicklei/go-restful/v3/log -# github.com/felixge/fgprof v0.9.3 +# github.com/felixge/fgprof v0.9.5 ## explicit; go 1.14 github.com/felixge/fgprof # github.com/felixge/httpsnoop v1.0.4 @@ -309,8 +309,8 @@ github.com/imdario/mergo # github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0 ## explicit github.com/jaytaylor/html2text -# github.com/jedib0t/go-pretty/v6 v6.6.5 -## explicit; go 1.17 +# github.com/jedib0t/go-pretty/v6 v6.6.7 +## explicit; go 1.18 github.com/jedib0t/go-pretty/v6/table github.com/jedib0t/go-pretty/v6/text # github.com/josharian/intern v1.0.0