11package client
22
33import (
4- "encoding/base64"
5- "encoding/json"
64 "fmt"
75 "io"
8- "net/http"
9- "net/url"
106 "os"
117 "path/filepath"
128 "strings"
139
10+ "github.com/docker/docker/api/client/lib"
1411 "github.com/docker/docker/api/types"
1512 Cli "github.com/docker/docker/cli"
1613 "github.com/docker/docker/pkg/archive"
@@ -129,38 +126,7 @@ func splitCpArg(arg string) (container, path string) {
129126}
130127
131128func (cli * DockerCli ) statContainerPath (containerName , path string ) (types.ContainerPathStat , error ) {
132- var stat types.ContainerPathStat
133-
134- query := make (url.Values , 1 )
135- query .Set ("path" , filepath .ToSlash (path )) // Normalize the paths used in the API.
136-
137- urlStr := fmt .Sprintf ("/containers/%s/archive?%s" , containerName , query .Encode ())
138-
139- response , err := cli .call ("HEAD" , urlStr , nil , nil )
140- if err != nil {
141- return stat , err
142- }
143- defer response .body .Close ()
144-
145- if response .statusCode != http .StatusOK {
146- return stat , fmt .Errorf ("unexpected status code from daemon: %d" , response .statusCode )
147- }
148-
149- return getContainerPathStatFromHeader (response .header )
150- }
151-
152- func getContainerPathStatFromHeader (header http.Header ) (types.ContainerPathStat , error ) {
153- var stat types.ContainerPathStat
154-
155- encodedStat := header .Get ("X-Docker-Container-Path-Stat" )
156- statDecoder := base64 .NewDecoder (base64 .StdEncoding , strings .NewReader (encodedStat ))
157-
158- err := json .NewDecoder (statDecoder ).Decode (& stat )
159- if err != nil {
160- err = fmt .Errorf ("unable to decode container path stat header: %s" , err )
161- }
162-
163- return stat , err
129+ return cli .client .StatContainerPath (containerName , path )
164130}
165131
166132func resolveLocalPath (localPath string ) (absPath string , err error ) {
@@ -200,39 +166,19 @@ func (cli *DockerCli) copyFromContainer(srcContainer, srcPath, dstPath string, c
200166
201167 }
202168
203- query := make (url.Values , 1 )
204- query .Set ("path" , filepath .ToSlash (srcPath )) // Normalize the paths used in the API.
205-
206- urlStr := fmt .Sprintf ("/containers/%s/archive?%s" , srcContainer , query .Encode ())
207-
208- response , err := cli .call ("GET" , urlStr , nil , nil )
169+ content , stat , err := cli .client .CopyFromContainer (srcContainer , srcPath )
209170 if err != nil {
210171 return err
211172 }
212- defer response .body .Close ()
213-
214- if response .statusCode != http .StatusOK {
215- return fmt .Errorf ("unexpected status code from daemon: %d" , response .statusCode )
216- }
173+ defer content .Close ()
217174
218175 if dstPath == "-" {
219176 // Send the response to STDOUT.
220- _ , err = io .Copy (os .Stdout , response . body )
177+ _ , err = io .Copy (os .Stdout , content )
221178
222179 return err
223180 }
224181
225- // In order to get the copy behavior right, we need to know information
226- // about both the source and the destination. The response headers include
227- // stat info about the source that we can use in deciding exactly how to
228- // copy it locally. Along with the stat info about the local destination,
229- // we have everything we need to handle the multiple possibilities there
230- // can be when copying a file/dir from one location to another file/dir.
231- stat , err := getContainerPathStatFromHeader (response .header )
232- if err != nil {
233- return fmt .Errorf ("unable to get resource stat from response: %s" , err )
234- }
235-
236182 // Prepare source copy info.
237183 srcInfo := archive.CopyInfo {
238184 Path : srcPath ,
@@ -241,10 +187,10 @@ func (cli *DockerCli) copyFromContainer(srcContainer, srcPath, dstPath string, c
241187 RebaseName : rebaseName ,
242188 }
243189
244- preArchive := response . body
190+ preArchive := content
245191 if len (srcInfo .RebaseName ) != 0 {
246192 _ , srcBase := archive .SplitPathDirEntry (srcInfo .Path )
247- preArchive = archive .RebaseArchiveEntries (response . body , srcBase , srcInfo .RebaseName )
193+ preArchive = archive .RebaseArchiveEntries (content , srcBase , srcInfo .RebaseName )
248194 }
249195 // See comments in the implementation of `archive.CopyTo` for exactly what
250196 // goes into deciding how and whether the source archive needs to be
@@ -340,22 +286,12 @@ func (cli *DockerCli) copyToContainer(srcPath, dstContainer, dstPath string, cpP
340286 content = preparedArchive
341287 }
342288
343- query := make (url.Values , 2 )
344- query .Set ("path" , filepath .ToSlash (resolvedDstPath )) // Normalize the paths used in the API.
345- // Do not allow for an existing directory to be overwritten by a non-directory and vice versa.
346- query .Set ("noOverwriteDirNonDir" , "true" )
347-
348- urlStr := fmt .Sprintf ("/containers/%s/archive?%s" , dstContainer , query .Encode ())
349-
350- response , err := cli .stream ("PUT" , urlStr , & streamOpts {in : content })
351- if err != nil {
352- return err
353- }
354- defer response .body .Close ()
355-
356- if response .statusCode != http .StatusOK {
357- return fmt .Errorf ("unexpected status code from daemon: %d" , response .statusCode )
289+ options := lib.CopyToContainerOptions {
290+ ContainerID : dstContainer ,
291+ Path : resolvedDstPath ,
292+ Content : content ,
293+ AllowOverwriteDirWithFile : false ,
358294 }
359295
360- return nil
296+ return cli . client . CopyToContainer ( options )
361297}
0 commit comments