diff --git a/graph/export.go b/graph/export.go index 7512127f7e..6362e54a6d 100644 --- a/graph/export.go +++ b/graph/export.go @@ -2,10 +2,12 @@ package graph import ( "encoding/json" + "fmt" "io" "io/ioutil" "os" "path/filepath" + "time" "github.com/Sirupsen/logrus" "github.com/docker/docker/pkg/archive" @@ -88,6 +90,9 @@ func (s *TagStore) ImageExport(names []string, outStream io.Writer) error { if err := f.Close(); err != nil { return err } + if err := os.Chtimes(filepath.Join(tempdir, "repositories"), time.Unix(0, 0), time.Unix(0, 0)); err != nil { + return err + } } else { logrus.Debugf("There were no repositories to write") } @@ -128,7 +133,11 @@ func (s *TagStore) exportImage(name, tempdir string) error { if err != nil { return err } - imageInspectRaw, err := s.lookupRaw(n) + img, err := s.LookupImage(n) + if err != nil || img == nil { + return fmt.Errorf("No such image %s", n) + } + imageInspectRaw, err := s.graph.RawJSON(img.ID) if err != nil { return err } @@ -149,11 +158,13 @@ func (s *TagStore) exportImage(name, tempdir string) error { return err } - // find parent - img, err := s.LookupImage(n) - if err != nil { - return err + for _, fname := range []string{"", "VERSION", "json", "layer.tar"} { + if err := os.Chtimes(filepath.Join(tmpImageDir, fname), img.Created, img.Created); err != nil { + return err + } } + + // try again with parent n = img.Parent } return nil diff --git a/graph/service.go b/graph/service.go index 1ecc08ccab..98a935c8d9 100644 --- a/graph/service.go +++ b/graph/service.go @@ -11,22 +11,6 @@ import ( "github.com/docker/docker/utils" ) -// lookupRaw looks up an image by name in a TagStore and returns the raw JSON -// describing the image. -func (s *TagStore) lookupRaw(name string) ([]byte, error) { - image, err := s.LookupImage(name) - if err != nil || image == nil { - return nil, fmt.Errorf("No such image %s", name) - } - - imageInspectRaw, err := s.graph.RawJSON(image.ID) - if err != nil { - return nil, err - } - - return imageInspectRaw, nil -} - // Lookup looks up an image by name in a TagStore and returns it as an // ImageInspect structure. func (s *TagStore) Lookup(name string) (*types.ImageInspect, error) { diff --git a/integration-cli/docker_cli_save_load_test.go b/integration-cli/docker_cli_save_load_test.go index d783b215f8..1fe694c8ff 100644 --- a/integration-cli/docker_cli_save_load_test.go +++ b/integration-cli/docker_cli_save_load_test.go @@ -1,6 +1,7 @@ package main import ( + "encoding/json" "fmt" "io/ioutil" "os" @@ -9,6 +10,7 @@ import ( "reflect" "sort" "strings" + "time" "github.com/go-check/check" ) @@ -97,6 +99,24 @@ func (s *DockerSuite) TestSaveSingleTag(c *check.C) { } } +func (s *DockerSuite) TestSaveCheckTimes(c *check.C) { + repoName := "busybox:latest" + out, _ := dockerCmd(c, "inspect", repoName) + data := []struct { + ID string + Created time.Time + }{} + err := json.Unmarshal([]byte(out), &data) + c.Assert(err, check.IsNil, check.Commentf("failed to marshal from %q: err %v", repoName, err)) + c.Assert(len(data), check.Not(check.Equals), 0, check.Commentf("failed to marshal the data from %q", repoName)) + tarTvTimeFormat := "2006-01-02 15:04" + out, _, err = runCommandPipelineWithOutput( + exec.Command(dockerBinary, "save", repoName), + exec.Command("tar", "tv"), + exec.Command("grep", "-E", fmt.Sprintf("%s %s", data[0].Created.Format(tarTvTimeFormat), data[0].ID))) + c.Assert(err, check.IsNil, check.Commentf("failed to save repo with image ID and 'repositories' file: %s, %v", out, err)) +} + func (s *DockerSuite) TestSaveImageId(c *check.C) { testRequires(c, DaemonIsLinux) repoName := "foobar-save-image-id-test"