Browse code

merge graph in graph

creack authored on 2013/03/21 22:35:57
Showing 7 changed files
... ...
@@ -387,7 +387,7 @@ func (srv *Server) CmdImport(stdin io.ReadCloser, stdout io.Writer, args ...stri
387 387
 		}
388 388
 		archive = ProgressReader(resp.Body, int(resp.ContentLength), stdout)
389 389
 	}
390
-	img, err := srv.runtime.graph.Create(archive, "", "Imported from "+src)
390
+	img, err := srv.runtime.graph.Create(archive, nil, "Imported from "+src)
391 391
 	if err != nil {
392 392
 		return err
393 393
 	}
... ...
@@ -737,33 +737,22 @@ func (srv *Server) CmdPs(stdin io.ReadCloser, stdout io.Writer, args ...string)
737 737
 
738 738
 func (srv *Server) CmdCommit(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
739 739
 	cmd := rcli.Subcmd(stdout,
740
-		"commit", "[OPTIONS] CONTAINER [DEST]",
740
+		"commit", "[OPTIONS] CONTAINER [REPOSITORY [TAG]]",
741 741
 		"Create a new image from a container's changes")
742 742
 	if err := cmd.Parse(args); err != nil {
743 743
 		return nil
744 744
 	}
745
-	containerName, imgName := cmd.Arg(0), cmd.Arg(1)
746
-	if containerName == "" || imgName == "" {
745
+	containerName, repository, tag := cmd.Arg(0), cmd.Arg(1), cmd.Arg(2)
746
+	if containerName == "" {
747 747
 		cmd.Usage()
748 748
 		return nil
749 749
 	}
750
-	if container := srv.runtime.Get(containerName); container != nil {
751
-		// FIXME: freeze the container before copying it to avoid data corruption?
752
-		// FIXME: this shouldn't be in commands.
753
-		rwTar, err := container.ExportRw()
754
-		if err != nil {
755
-			return err
756
-		}
757
-		// Create a new image from the container's base layers + a new layer from container changes
758
-		img, err := srv.runtime.graph.Create(rwTar, container.Image, "")
759
-		if err != nil {
760
-			return err
761
-		}
762
-
763
-		fmt.Fprintln(stdout, img.Id)
764
-		return nil
750
+	img, err := srv.runtime.Commit(containerName, repository, tag)
751
+	if err != nil {
752
+		return err
765 753
 	}
766
-	return errors.New("No such container: " + containerName)
754
+	fmt.Fprintln(stdout, img.Id)
755
+	return nil
767 756
 }
768 757
 
769 758
 func (srv *Server) CmdExport(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
... ...
@@ -46,7 +46,7 @@ func TestCommitRun(t *testing.T) {
46 46
 	if err != nil {
47 47
 		t.Error(err)
48 48
 	}
49
-	img, err := runtime.graph.Create(rwTar, container1.Image, "unit test commited image")
49
+	img, err := runtime.graph.Create(rwTar, container1, "unit test commited image")
50 50
 	if err != nil {
51 51
 		t.Error(err)
52 52
 	}
... ...
@@ -47,13 +47,17 @@ func (graph *Graph) Get(id string) (*Image, error) {
47 47
 	return img, nil
48 48
 }
49 49
 
50
-func (graph *Graph) Create(layerData Archive, parent, comment string) (*Image, error) {
50
+func (graph *Graph) Create(layerData Archive, container *Container, comment string) (*Image, error) {
51 51
 	img := &Image{
52 52
 		Id:      GenerateId(),
53
-		Parent:  parent,
54 53
 		Comment: comment,
55 54
 		Created: time.Now(),
56 55
 	}
56
+	if container != nil {
57
+		img.Parent = container.Image
58
+		img.ParentContainer = container.Id
59
+		img.ParentCommand = append([]string{container.Path}, container.Args...)
60
+	}
57 61
 	if err := graph.Register(layerData, img); err != nil {
58 62
 		return nil, err
59 63
 	}
... ...
@@ -35,7 +35,7 @@ func TestGraphCreate(t *testing.T) {
35 35
 	if err != nil {
36 36
 		t.Fatal(err)
37 37
 	}
38
-	image, err := graph.Create(archive, "", "Testing")
38
+	image, err := graph.Create(archive, nil, "Testing")
39 39
 	if err != nil {
40 40
 		t.Fatal(err)
41 41
 	}
... ...
@@ -92,7 +92,7 @@ func TestMount(t *testing.T) {
92 92
 	if err != nil {
93 93
 		t.Fatal(err)
94 94
 	}
95
-	image, err := graph.Create(archive, "", "Testing")
95
+	image, err := graph.Create(archive, nil, "Testing")
96 96
 	if err != nil {
97 97
 		t.Fatal(err)
98 98
 	}
... ...
@@ -128,7 +128,7 @@ func TestDelete(t *testing.T) {
128 128
 		t.Fatal(err)
129 129
 	}
130 130
 	assertNImages(graph, t, 0)
131
-	img, err := graph.Create(archive, "", "Bla bla")
131
+	img, err := graph.Create(archive, nil, "Bla bla")
132 132
 	if err != nil {
133 133
 		t.Fatal(err)
134 134
 	}
... ...
@@ -139,11 +139,11 @@ func TestDelete(t *testing.T) {
139 139
 	assertNImages(graph, t, 0)
140 140
 
141 141
 	// Test 2 create (same name) / 1 delete
142
-	img1, err := graph.Create(archive, "foo", "Testing")
142
+	img1, err := graph.Create(archive, nil, "Testing")
143 143
 	if err != nil {
144 144
 		t.Fatal(err)
145 145
 	}
146
-	if _, err = graph.Create(archive, "foo", "Testing"); err != nil {
146
+	if _, err = graph.Create(archive, nil, "Testing"); err != nil {
147 147
 		t.Fatal(err)
148 148
 	}
149 149
 	assertNImages(graph, t, 2)
... ...
@@ -15,11 +15,13 @@ import (
15 15
 )
16 16
 
17 17
 type Image struct {
18
-	Id      string    `json:"id"`
19
-	Parent  string    `json:"parent,omitempty"`
20
-	Comment string    `json:"comment,omitempty"`
21
-	Created time.Time `json:"created"`
22
-	graph   *Graph
18
+	Id              string    `json:"id"`
19
+	Parent          string    `json:"parent,omitempty"`
20
+	Comment         string    `json:"comment,omitempty"`
21
+	Created         time.Time `json:"created"`
22
+	ParentContainer string    `json:-`
23
+	ParentCommand   []string  `json:-`
24
+	graph           *Graph
23 25
 }
24 26
 
25 27
 func LoadImage(root string) (*Image, error) {
... ...
@@ -200,6 +200,33 @@ func (runtime *Runtime) Destroy(container *Container) error {
200 200
 	return nil
201 201
 }
202 202
 
203
+// Commit creates a new filesystem image from the current state of a container.
204
+// The image can optionally be tagged into a repository
205
+func (runtime *Runtime) Commit(id, repository, tag string) (*Image, error) {
206
+	container := runtime.Get(id)
207
+	if container == nil {
208
+		return nil, fmt.Errorf("No such container: %s", id)
209
+	}
210
+	// FIXME: freeze the container before copying it to avoid data corruption?
211
+	// FIXME: this shouldn't be in commands.
212
+	rwTar, err := container.ExportRw()
213
+	if err != nil {
214
+		return nil, err
215
+	}
216
+	// Create a new image from the container's base layers + a new layer from container changes
217
+	img, err := runtime.graph.Create(rwTar, container, "")
218
+	if err != nil {
219
+		return nil, err
220
+	}
221
+	// Register the image if needed
222
+	if repository != "" {
223
+		if err := runtime.repositories.Set(repository, tag, img.Id); err != nil {
224
+			return img, err
225
+		}
226
+	}
227
+	return img, nil
228
+}
229
+
203 230
 func (runtime *Runtime) restore() error {
204 231
 	dir, err := ioutil.ReadDir(runtime.repository)
205 232
 	if err != nil {
... ...
@@ -2,9 +2,11 @@ package docker
2 2
 
3 3
 import (
4 4
 	"encoding/json"
5
+	"fmt"
5 6
 	"io/ioutil"
6 7
 	"os"
7 8
 	"path/filepath"
9
+	"strings"
8 10
 )
9 11
 
10 12
 type TagStore struct {
... ...
@@ -60,6 +62,12 @@ func (store *TagStore) Reload() error {
60 60
 }
61 61
 
62 62
 func (store *TagStore) Set(repoName, tag, revision string) error {
63
+	if strings.Contains(repoName, ":") {
64
+		return fmt.Errorf("Illegal repository name: %s", repoName)
65
+	}
66
+	if strings.Contains(repoName, ":") {
67
+		return fmt.Errorf("Illegal tag name: %s", tag)
68
+	}
63 69
 	if err := store.Reload(); err != nil {
64 70
 		return err
65 71
 	}