Skip to content

Commit

Permalink
Make CopyFileWithTar use a pipe instead of a buffer. Save more than 1…
Browse files Browse the repository at this point in the history
…Gb of ram for a 500Mb file.
  • Loading branch information
Guillaume J. Charmes committed Jan 7, 2014
1 parent f43f3fa commit 444a087
Showing 1 changed file with 34 additions and 21 deletions.
55 changes: 34 additions & 21 deletions archive/archive.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package archive
import (
"archive/tar"
"bytes"
"compress/gzip"
"compress/bzip2"
"compress/gzip"
"fmt"
"github.com/dotcloud/docker/utils"
"io"
Expand Down Expand Up @@ -299,7 +299,7 @@ func CopyWithTar(src, dst string) error {
//
// If `dst` ends with a trailing slash '/', the final destination path
// will be `dst/base(src)`.
func CopyFileWithTar(src, dst string) error {
func CopyFileWithTar(src, dst string) (err error) {
utils.Debugf("CopyFileWithTar(%s, %s)", src, dst)
srcSt, err := os.Stat(src)
if err != nil {
Expand All @@ -316,25 +316,38 @@ func CopyFileWithTar(src, dst string) error {
if err := os.MkdirAll(filepath.Dir(dst), 0700); err != nil && !os.IsExist(err) {
return err
}
buf := new(bytes.Buffer)
tw := tar.NewWriter(buf)
hdr, err := tar.FileInfoHeader(srcSt, "")
if err != nil {
return err
}
hdr.Name = filepath.Base(dst)
if err := tw.WriteHeader(hdr); err != nil {
return err
}
srcF, err := os.Open(src)
if err != nil {
return err
}
if _, err := io.Copy(tw, srcF); err != nil {
return err
}
tw.Close()
return Untar(buf, filepath.Dir(dst), nil)

r, w := io.Pipe()
errC := utils.Go(func() error {
defer w.Close()

srcF, err := os.Open(src)
if err != nil {
return err
}
defer srcF.Close()

tw := tar.NewWriter(w)
hdr, err := tar.FileInfoHeader(srcSt, "")
if err != nil {
return err
}
hdr.Name = filepath.Base(dst)
if err := tw.WriteHeader(hdr); err != nil {
return err
}
if _, err := io.Copy(tw, srcF); err != nil {
return err
}
tw.Close()
return nil
})
defer func() {
if er := <-errC; err != nil {
err = er
}
}()
return Untar(r, filepath.Dir(dst), nil)
}

// CmdStream executes a command, and returns its stdout as a stream.
Expand Down

0 comments on commit 444a087

Please sign in to comment.