MCPcopy Index your code
hub / github.com/docker/cli / copyProgress

Function copyProgress

cli/command/container/cp.go:70–122  ·  view source on GitHub ↗
(ctx context.Context, dst io.Writer, header string, total *int64)

Source from the content-addressed store, hash-verified

68}
69
70func copyProgress(ctx context.Context, dst io.Writer, header string, total *int64) (func(), <-chan struct{}) {
71 done := make(chan struct{})
72 if !streams.NewOut(dst).IsTerminal() {
73 close(done)
74 return func() {}, done
75 }
76
77 fmt.Fprint(dst, aec.Save)
78 fmt.Fprint(dst, "Preparing to copy...")
79
80 restore := func() {
81 fmt.Fprint(dst, aec.Restore)
82 fmt.Fprint(dst, aec.EraseLine(aec.EraseModes.All))
83 }
84
85 go func() {
86 defer close(done)
87 fmt.Fprint(dst, aec.Hide)
88 defer fmt.Fprint(dst, aec.Show)
89
90 fmt.Fprint(dst, aec.Restore)
91 fmt.Fprint(dst, aec.EraseLine(aec.EraseModes.All))
92 fmt.Fprint(dst, header)
93
94 var last int64
95 fmt.Fprint(dst, progressHumanSize(last))
96
97 buf := bytes.NewBuffer(nil)
98 ticker := time.NewTicker(copyProgressUpdateThreshold)
99 for {
100 select {
101 case <-ctx.Done():
102 return
103 case <-ticker.C:
104 n := atomic.LoadInt64(total)
105 if n == last {
106 // Don't write to the terminal, if we don't need to.
107 continue
108 }
109
110 // Write to the buffer first to avoid flickering and context switching
111 fmt.Fprint(buf, aec.Column(uint(len(header)+1)))
112 fmt.Fprint(buf, aec.EraseLine(aec.EraseModes.Tail))
113 fmt.Fprint(buf, progressHumanSize(n))
114
115 buf.WriteTo(dst)
116 buf.Reset()
117 last += n
118 }
119 }
120 }()
121 return restore, done
122}
123
124// newCopyCommand creates a new `docker cp` command
125func newCopyCommand(dockerCLI command.Cli) *cobra.Command {

Callers 2

copyFromContainerFunction · 0.85
copyToContainerFunction · 0.85

Calls 2

progressHumanSizeFunction · 0.85
IsTerminalMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…