From f813c9639f89a029364b62a287b24965d56e4615 Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Wed, 29 Mar 2023 23:47:50 +0000 Subject: [PATCH] cp: Improve tty flashing on progress updates - Instead of rewriting the entire line every time only clear and write the parts that changed. - Hide the cursor while writing progress Both these things make the progress updates significantly easier to read. Signed-off-by: Brian Goff (cherry picked from commit ccae6e9299e9c2d7c9e53bd4a485d43581a795ee) Signed-off-by: Brian Goff --- cli/command/container/cp.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/cli/command/container/cp.go b/cli/command/container/cp.go index 0ac209ea14..42205918c3 100644 --- a/cli/command/container/cp.go +++ b/cli/command/container/cp.go @@ -58,16 +58,24 @@ type copyProgressPrinter struct { func (pt *copyProgressPrinter) Read(p []byte) (int, error) { n, err := pt.ReadCloser.Read(p) if n > 0 { + isFirst := *pt.total == 0 *pt.total += float64(n) if pt.isTerm { - fmt.Fprint(pt.writer, aec.Restore) - fmt.Fprint(pt.writer, aec.EraseLine(aec.EraseModes.All)) + var header string if pt.toContainer { - fmt.Fprintln(pt.writer, "Copying to container - "+units.HumanSize(*pt.total)) + header = "Copying to container - " } else { - fmt.Fprintln(pt.writer, "Copying from container - "+units.HumanSize(*pt.total)) + header = "Copying from container - " } + if isFirst { + fmt.Fprint(pt.writer, aec.Restore) + fmt.Fprint(pt.writer, aec.EraseLine(aec.EraseModes.All)) + fmt.Fprint(pt.writer, header) + } + fmt.Fprint(pt.writer, aec.Column(uint(len(header)+1))) + fmt.Fprint(pt.writer, aec.EraseLine(aec.EraseModes.Tail)) + fmt.Fprint(pt.writer, units.HumanSize(*pt.total)) } } @@ -239,6 +247,7 @@ func copyFromContainer(ctx context.Context, dockerCli command.Cli, copyConfig cp } if stderrIsTerm { + fmt.Fprint(dockerCli.Err(), aec.Hide) fmt.Fprint(dockerCli.Err(), aec.Save) fmt.Fprintln(dockerCli.Err(), "Preparing to copy...") } @@ -246,6 +255,7 @@ func copyFromContainer(ctx context.Context, dockerCli command.Cli, copyConfig cp if stderrIsTerm { fmt.Fprint(dockerCli.Err(), aec.Restore) fmt.Fprint(dockerCli.Err(), aec.EraseLine(aec.EraseModes.All)) + fmt.Fprint(dockerCli.Err(), aec.Show) } fmt.Fprintln(dockerCli.Err(), "Successfully copied", units.HumanSize(copiedSize), "to", dstPath) @@ -369,6 +379,7 @@ func copyToContainer(ctx context.Context, dockerCli command.Cli, copyConfig cpCo } if stderrIsTerm { + fmt.Fprint(dockerCli.Err(), aec.Hide) fmt.Fprint(dockerCli.Err(), aec.Save) fmt.Fprintln(dockerCli.Err(), "Preparing to copy...") } @@ -376,6 +387,7 @@ func copyToContainer(ctx context.Context, dockerCli command.Cli, copyConfig cpCo if stderrIsTerm { fmt.Fprint(dockerCli.Err(), aec.Restore) fmt.Fprint(dockerCli.Err(), aec.EraseLine(aec.EraseModes.All)) + fmt.Fprint(dockerCli.Err(), aec.Show) } fmt.Fprintln(dockerCli.Err(), "Successfully copied", units.HumanSize(copiedSize), "to", copyConfig.container+":"+dstInfo.Path)