mirror of
https://github.com/token2/snapd.git
synced 2026-03-13 11:15:47 -07:00
Some languages may use multibyte characters for duration. In such case, the width of the progress bar would be incorrectly calculated, making the displayed label too short. At runtime this would randomly cause a panic with the translation used a multibyte characters: panic: runtime error: slice bounds out of range [80:79] [recovered] panic: runtime error: slice bounds out of range [80:79] goroutine 1 [running]: main.main.func1() github.com/snapcore/snapd/cmd/snap/main.go:477 +0x95 panic(0x561d5f7fac80, 0xc000144280) runtime/panic.go:679 +0x1b6 github.com/snapcore/snapd/progress.(*ANSIMeter).Set(0xc000214eb0, 0x41a891a000000000) github.com/snapcore/snapd/progress/ansimeter.go:152 +0xa1b main.waitMixin.wait(0xc0002e42a0, 0x561d5f3e0000, 0xc0001e4488, 0x2, 0x0, 0x0, 0x0) github.com/snapcore/snapd/cmd/snap/wait.go:130 +0x700 main.(*cmdInstall).installOne(0xc000359040, 0x7ffcf44c33e4, 0xb, 0x0, 0x0, 0xc00036cba0, 0x561d5f805060, 0x561d5f8693a0) github.com/snapcore/snapd/cmd/snap/cmd_snap_op.go:491 +0x316 main.(*cmdInstall).Execute(0xc000359040, 0xc0003787a0, 0x0, 0x2, 0xc000359040, 0x1) github.com/snapcore/snapd/cmd/snap/cmd_snap_op.go:596 +0x3d7 github.com/snapcore/snapd/vendor/github.com/jessevdk/go-flags.(*Parser).ParseArgs(0xc000316bd0, 0xc000032190, 0x2, 0x2, 0xc000330330, 0xc0002a5cd0, 0x561d5ee49fbd, 0x561d5f7d08a0, 0xc000330330) github.com/snapcore/snapd/vendor/github.com/jessevdk/go-flags/parser.go:333 +0x8e7 github.com/snapcore/snapd/vendor/github.com/jessevdk/go-flags.(*Parser).Parse(...) github.com/snapcore/snapd/vendor/github.com/jessevdk/go-flags/parser.go:190 main.run(0xc0002a5de0, 0xe) github.com/snapcore/snapd/cmd/snap/main.go:515 +0xa7 main.main() github.com/snapcore/snapd/cmd/snap/main.go:482 +0x371 Since we are assuming that terminal can display up to the column number of runes, fix the length calculation to use slices of runes for all components (keep in mind that len(string) >= len([]rune)). Fixes: https://bugs.launchpad.net/ubuntu/+source/snapd/+bug/1876583 Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
111 lines
2.3 KiB
Go
111 lines
2.3 KiB
Go
// -*- Mode: Go; indent-tabs-mode: t -*-
|
|
|
|
/*
|
|
* Copyright (C) 2017 Canonical Ltd
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 3 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
package progress
|
|
|
|
import (
|
|
"io"
|
|
)
|
|
|
|
var (
|
|
ClrEOL = clrEOL
|
|
CursorInvisible = cursorInvisible
|
|
CursorVisible = cursorVisible
|
|
EnterReverseMode = enterReverseMode
|
|
ExitAttributeMode = exitAttributeMode
|
|
)
|
|
|
|
func MockEmptyEscapes() func() {
|
|
clrEOL = ""
|
|
cursorInvisible = ""
|
|
cursorVisible = ""
|
|
enterReverseMode = ""
|
|
exitAttributeMode = ""
|
|
|
|
return func() {
|
|
clrEOL = ClrEOL
|
|
cursorInvisible = CursorInvisible
|
|
cursorVisible = CursorVisible
|
|
enterReverseMode = EnterReverseMode
|
|
exitAttributeMode = ExitAttributeMode
|
|
}
|
|
}
|
|
|
|
func MockSimpleEscapes() func() {
|
|
// set them to the tcap name (in all caps)
|
|
clrEOL = "<CE>"
|
|
cursorInvisible = "<VI>"
|
|
cursorVisible = "<VS>"
|
|
enterReverseMode = "<MR>"
|
|
exitAttributeMode = "<ME>"
|
|
|
|
return func() {
|
|
clrEOL = ClrEOL
|
|
cursorInvisible = CursorInvisible
|
|
cursorVisible = CursorVisible
|
|
enterReverseMode = EnterReverseMode
|
|
exitAttributeMode = ExitAttributeMode
|
|
}
|
|
}
|
|
|
|
func (p *ANSIMeter) Percent() string {
|
|
return p.percent()
|
|
}
|
|
|
|
func (p *ANSIMeter) SetWritten(written float64) {
|
|
p.written = written
|
|
}
|
|
|
|
func (p *ANSIMeter) GetWritten() float64 {
|
|
return p.written
|
|
}
|
|
|
|
func (p *ANSIMeter) GetTotal() float64 {
|
|
return p.total
|
|
}
|
|
|
|
func MockTermWidth(f func() int) func() {
|
|
origTermWidth := termWidth
|
|
termWidth = f
|
|
return func() {
|
|
termWidth = origTermWidth
|
|
}
|
|
}
|
|
|
|
func MockStdout(w io.Writer) func() {
|
|
origStdout := stdout
|
|
stdout = w
|
|
return func() {
|
|
stdout = origStdout
|
|
}
|
|
}
|
|
|
|
func MockFormatDuration(m func(f float64) string) (restore func()) {
|
|
old := formatDuration
|
|
formatDuration = m
|
|
return func() {
|
|
formatDuration = old
|
|
}
|
|
}
|
|
|
|
var (
|
|
Norm = norm
|
|
Spinner = spinner
|
|
)
|