This commit is contained in:
98
vendor/github.com/docker/cli/internal/lazyregexp/lazyregexp.go
generated
vendored
Normal file
98
vendor/github.com/docker/cli/internal/lazyregexp/lazyregexp.go
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Code below was largely copied from golang.org/x/mod@v0.22;
|
||||
// https://github.com/golang/mod/blob/v0.22.0/internal/lazyregexp/lazyre.go
|
||||
// with some additional methods added.
|
||||
|
||||
// Package lazyregexp is a thin wrapper over regexp, allowing the use of global
|
||||
// regexp variables without forcing them to be compiled at init.
|
||||
package lazyregexp
|
||||
|
||||
import (
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Regexp is a wrapper around [regexp.Regexp], where the underlying regexp will be
|
||||
// compiled the first time it is needed.
|
||||
type Regexp struct {
|
||||
str string
|
||||
once sync.Once
|
||||
rx *regexp.Regexp
|
||||
}
|
||||
|
||||
func (r *Regexp) re() *regexp.Regexp {
|
||||
r.once.Do(r.build)
|
||||
return r.rx
|
||||
}
|
||||
|
||||
func (r *Regexp) build() {
|
||||
r.rx = regexp.MustCompile(r.str)
|
||||
r.str = ""
|
||||
}
|
||||
|
||||
func (r *Regexp) FindSubmatch(s []byte) [][]byte {
|
||||
return r.re().FindSubmatch(s)
|
||||
}
|
||||
|
||||
func (r *Regexp) FindAllStringSubmatch(s string, n int) [][]string {
|
||||
return r.re().FindAllStringSubmatch(s, n)
|
||||
}
|
||||
|
||||
func (r *Regexp) FindStringSubmatch(s string) []string {
|
||||
return r.re().FindStringSubmatch(s)
|
||||
}
|
||||
|
||||
func (r *Regexp) FindStringSubmatchIndex(s string) []int {
|
||||
return r.re().FindStringSubmatchIndex(s)
|
||||
}
|
||||
|
||||
func (r *Regexp) ReplaceAllString(src, repl string) string {
|
||||
return r.re().ReplaceAllString(src, repl)
|
||||
}
|
||||
|
||||
func (r *Regexp) FindString(s string) string {
|
||||
return r.re().FindString(s)
|
||||
}
|
||||
|
||||
func (r *Regexp) FindAllString(s string, n int) []string {
|
||||
return r.re().FindAllString(s, n)
|
||||
}
|
||||
|
||||
func (r *Regexp) MatchString(s string) bool {
|
||||
return r.re().MatchString(s)
|
||||
}
|
||||
|
||||
func (r *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string {
|
||||
return r.re().ReplaceAllStringFunc(src, repl)
|
||||
}
|
||||
|
||||
func (r *Regexp) ReplaceAllLiteralString(src, repl string) string {
|
||||
return r.re().ReplaceAllLiteralString(src, repl)
|
||||
}
|
||||
|
||||
func (r *Regexp) String() string {
|
||||
return r.re().String()
|
||||
}
|
||||
|
||||
func (r *Regexp) SubexpNames() []string {
|
||||
return r.re().SubexpNames()
|
||||
}
|
||||
|
||||
var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test")
|
||||
|
||||
// New creates a new lazy regexp, delaying the compiling work until it is first
|
||||
// needed. If the code is being run as part of tests, the regexp compiling will
|
||||
// happen immediately.
|
||||
func New(str string) *Regexp {
|
||||
lr := &Regexp{str: str}
|
||||
if inTest {
|
||||
// In tests, always compile the regexps early.
|
||||
lr.re()
|
||||
}
|
||||
return lr
|
||||
}
|
116
vendor/github.com/docker/cli/internal/prompt/prompt.go
generated
vendored
Normal file
116
vendor/github.com/docker/cli/internal/prompt/prompt.go
generated
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
// Package prompt provides utilities to prompt the user for input.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/cli/cli/streams"
|
||||
"github.com/moby/term"
|
||||
)
|
||||
|
||||
const ErrTerminated cancelledErr = "prompt terminated"
|
||||
|
||||
type cancelledErr string
|
||||
|
||||
func (e cancelledErr) Error() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
func (cancelledErr) Cancelled() {}
|
||||
|
||||
// DisableInputEcho disables input echo on the provided streams.In.
|
||||
// This is useful when the user provides sensitive information like passwords.
|
||||
// The function returns a restore function that should be called to restore the
|
||||
// terminal state.
|
||||
//
|
||||
// TODO(thaJeztah): implement without depending on streams?
|
||||
func DisableInputEcho(ins *streams.In) (restore func() error, _ error) {
|
||||
oldState, err := term.SaveState(ins.FD())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
restore = func() error {
|
||||
return term.RestoreTerminal(ins.FD(), oldState)
|
||||
}
|
||||
return restore, term.DisableEcho(ins.FD(), oldState)
|
||||
}
|
||||
|
||||
// ReadInput requests input from the user.
|
||||
//
|
||||
// It returns an empty string ("") with an [ErrTerminated] if the user terminates
|
||||
// the CLI with SIGINT or SIGTERM while the prompt is active. If the prompt
|
||||
// returns an error, the caller should close the [io.Reader] used for the prompt
|
||||
// and propagate the error up the stack to prevent the background goroutine
|
||||
// from blocking indefinitely.
|
||||
func ReadInput(ctx context.Context, in io.Reader, out io.Writer, message string) (string, error) {
|
||||
_, _ = out.Write([]byte(message))
|
||||
|
||||
result := make(chan string)
|
||||
go func() {
|
||||
scanner := bufio.NewScanner(in)
|
||||
if scanner.Scan() {
|
||||
result <- strings.TrimSpace(scanner.Text())
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
_, _ = out.Write([]byte("\n"))
|
||||
return "", ErrTerminated
|
||||
case r := <-result:
|
||||
return r, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Confirm requests and checks confirmation from the user.
|
||||
//
|
||||
// It displays the provided message followed by "[y/N]". If the user
|
||||
// input 'y' or 'Y' it returns true otherwise false. If no message is provided,
|
||||
// "Are you sure you want to proceed? [y/N] " will be used instead.
|
||||
//
|
||||
// It returns false with an [ErrTerminated] if the user terminates
|
||||
// the CLI with SIGINT or SIGTERM while the prompt is active. If the prompt
|
||||
// returns an error, the caller should close the [io.Reader] used for the prompt
|
||||
// and propagate the error up the stack to prevent the background goroutine
|
||||
// from blocking indefinitely.
|
||||
func Confirm(ctx context.Context, in io.Reader, out io.Writer, message string) (bool, error) {
|
||||
if message == "" {
|
||||
message = "Are you sure you want to proceed?"
|
||||
}
|
||||
message += " [y/N] "
|
||||
|
||||
_, _ = out.Write([]byte(message))
|
||||
|
||||
// On Windows, force the use of the regular OS stdin stream.
|
||||
if runtime.GOOS == "windows" {
|
||||
in = streams.NewIn(os.Stdin)
|
||||
}
|
||||
|
||||
result := make(chan bool)
|
||||
|
||||
go func() {
|
||||
var res bool
|
||||
scanner := bufio.NewScanner(in)
|
||||
if scanner.Scan() {
|
||||
answer := strings.TrimSpace(scanner.Text())
|
||||
if strings.EqualFold(answer, "y") {
|
||||
res = true
|
||||
}
|
||||
}
|
||||
result <- res
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
_, _ = out.Write([]byte("\n"))
|
||||
return false, ErrTerminated
|
||||
case r := <-result:
|
||||
return r, nil
|
||||
}
|
||||
}
|
2
vendor/github.com/docker/cli/internal/tui/chip.go
generated
vendored
2
vendor/github.com/docker/cli/internal/tui/chip.go
generated
vendored
@ -1,5 +1,5 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.22
|
||||
//go:build go1.23
|
||||
|
||||
package tui
|
||||
|
||||
|
2
vendor/github.com/docker/cli/internal/tui/colors.go
generated
vendored
2
vendor/github.com/docker/cli/internal/tui/colors.go
generated
vendored
@ -1,5 +1,5 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.22
|
||||
//go:build go1.23
|
||||
|
||||
package tui
|
||||
|
||||
|
2
vendor/github.com/docker/cli/internal/tui/count.go
generated
vendored
2
vendor/github.com/docker/cli/internal/tui/count.go
generated
vendored
@ -1,5 +1,5 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.22
|
||||
//go:build go1.23
|
||||
|
||||
package tui
|
||||
|
||||
|
43
vendor/github.com/docker/cli/internal/tui/note.go
generated
vendored
43
vendor/github.com/docker/cli/internal/tui/note.go
generated
vendored
@ -1,5 +1,5 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.22
|
||||
//go:build go1.23
|
||||
|
||||
package tui
|
||||
|
||||
@ -15,19 +15,39 @@ var InfoHeader = Str{
|
||||
Fancy: aec.Bold.Apply(aec.LightCyanB.Apply(aec.BlackF.Apply("i")) + " " + aec.LightCyanF.Apply("Info → ")),
|
||||
}
|
||||
|
||||
func (o Output) PrintNote(format string, args ...any) {
|
||||
type options struct {
|
||||
header Str
|
||||
}
|
||||
|
||||
type noteOptions func(o *options)
|
||||
|
||||
func withHeader(header Str) noteOptions {
|
||||
return func(o *options) {
|
||||
o.header = header
|
||||
}
|
||||
}
|
||||
|
||||
func (o Output) printNoteWithOptions(format string, args []any, opts ...noteOptions) {
|
||||
if o.isTerminal {
|
||||
// TODO: Handle all flags
|
||||
format = strings.ReplaceAll(format, "--platform", ColorFlag.Apply("--platform"))
|
||||
}
|
||||
|
||||
header := o.Sprint(InfoHeader)
|
||||
opt := &options{
|
||||
header: InfoHeader,
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprint(o, "\n", header)
|
||||
for _, override := range opts {
|
||||
override(opt)
|
||||
}
|
||||
|
||||
h := o.Sprint(opt.header)
|
||||
|
||||
_, _ = fmt.Fprint(o, "\n", h)
|
||||
s := fmt.Sprintf(format, args...)
|
||||
for idx, line := range strings.Split(s, "\n") {
|
||||
if idx > 0 {
|
||||
_, _ = fmt.Fprint(o, strings.Repeat(" ", Width(header)))
|
||||
_, _ = fmt.Fprint(o, strings.Repeat(" ", Width(h)))
|
||||
}
|
||||
|
||||
l := line
|
||||
@ -37,3 +57,16 @@ func (o Output) PrintNote(format string, args ...any) {
|
||||
_, _ = fmt.Fprintln(o, l)
|
||||
}
|
||||
}
|
||||
|
||||
func (o Output) PrintNote(format string, args ...any) {
|
||||
o.printNoteWithOptions(format, args, withHeader(InfoHeader))
|
||||
}
|
||||
|
||||
var warningHeader = Str{
|
||||
Plain: " Warn -> ",
|
||||
Fancy: aec.Bold.Apply(aec.LightYellowB.Apply(aec.BlackF.Apply("w")) + " " + ColorWarning.Apply("Warn → ")),
|
||||
}
|
||||
|
||||
func (o Output) PrintWarning(format string, args ...any) {
|
||||
o.printNoteWithOptions(format, args, withHeader(warningHeader))
|
||||
}
|
||||
|
2
vendor/github.com/docker/cli/internal/tui/output.go
generated
vendored
2
vendor/github.com/docker/cli/internal/tui/output.go
generated
vendored
@ -1,5 +1,5 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.22
|
||||
//go:build go1.23
|
||||
|
||||
package tui
|
||||
|
||||
|
2
vendor/github.com/docker/cli/internal/tui/str.go
generated
vendored
2
vendor/github.com/docker/cli/internal/tui/str.go
generated
vendored
@ -1,5 +1,5 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.22
|
||||
//go:build go1.23
|
||||
|
||||
package tui
|
||||
|
||||
|
Reference in New Issue
Block a user