Browse code

abstract the string slice struct to stringutils package

Signed-off-by: Shijiang Wei <mountkin@gmail.com>

Shijiang Wei authored on 2015/08/29 00:29:10
Showing 11 changed files
... ...
@@ -20,6 +20,7 @@ import (
20 20
 	"github.com/Sirupsen/logrus"
21 21
 	flag "github.com/docker/docker/pkg/mflag"
22 22
 	"github.com/docker/docker/pkg/nat"
23
+	"github.com/docker/docker/pkg/stringutils"
23 24
 	"github.com/docker/docker/runconfig"
24 25
 )
25 26
 
... ...
@@ -352,7 +353,7 @@ func run(b *builder, args []string, attributes map[string]bool, original string)
352 352
 	b.Config.Cmd = config.Cmd
353 353
 	runconfig.Merge(b.Config, config)
354 354
 
355
-	defer func(cmd *runconfig.Command) { b.Config.Cmd = cmd }(cmd)
355
+	defer func(cmd *stringutils.StrSlice) { b.Config.Cmd = cmd }(cmd)
356 356
 
357 357
 	logrus.Debugf("[BUILDER] Command to be executed: %v", b.Config.Cmd)
358 358
 
... ...
@@ -405,7 +406,7 @@ func cmd(b *builder, args []string, attributes map[string]bool, original string)
405 405
 		}
406 406
 	}
407 407
 
408
-	b.Config.Cmd = runconfig.NewCommand(cmdSlice...)
408
+	b.Config.Cmd = stringutils.NewStrSlice(cmdSlice...)
409 409
 
410 410
 	if err := b.commit("", b.Config.Cmd, fmt.Sprintf("CMD %q", cmdSlice)); err != nil {
411 411
 		return err
... ...
@@ -436,16 +437,16 @@ func entrypoint(b *builder, args []string, attributes map[string]bool, original
436 436
 	switch {
437 437
 	case attributes["json"]:
438 438
 		// ENTRYPOINT ["echo", "hi"]
439
-		b.Config.Entrypoint = runconfig.NewEntrypoint(parsed...)
439
+		b.Config.Entrypoint = stringutils.NewStrSlice(parsed...)
440 440
 	case len(parsed) == 0:
441 441
 		// ENTRYPOINT []
442 442
 		b.Config.Entrypoint = nil
443 443
 	default:
444 444
 		// ENTRYPOINT echo hi
445 445
 		if runtime.GOOS != "windows" {
446
-			b.Config.Entrypoint = runconfig.NewEntrypoint("/bin/sh", "-c", parsed[0])
446
+			b.Config.Entrypoint = stringutils.NewStrSlice("/bin/sh", "-c", parsed[0])
447 447
 		} else {
448
-			b.Config.Entrypoint = runconfig.NewEntrypoint("cmd", "/S /C", parsed[0])
448
+			b.Config.Entrypoint = stringutils.NewStrSlice("cmd", "/S /C", parsed[0])
449 449
 		}
450 450
 	}
451 451
 
... ...
@@ -33,6 +33,7 @@ import (
33 33
 	"github.com/docker/docker/pkg/parsers"
34 34
 	"github.com/docker/docker/pkg/progressreader"
35 35
 	"github.com/docker/docker/pkg/stringid"
36
+	"github.com/docker/docker/pkg/stringutils"
36 37
 	"github.com/docker/docker/pkg/system"
37 38
 	"github.com/docker/docker/pkg/tarsum"
38 39
 	"github.com/docker/docker/pkg/urlutil"
... ...
@@ -73,7 +74,7 @@ func (b *builder) readContext(context io.Reader) (err error) {
73 73
 	return
74 74
 }
75 75
 
76
-func (b *builder) commit(id string, autoCmd *runconfig.Command, comment string) error {
76
+func (b *builder) commit(id string, autoCmd *stringutils.StrSlice, comment string) error {
77 77
 	if b.disableCommit {
78 78
 		return nil
79 79
 	}
... ...
@@ -84,11 +85,11 @@ func (b *builder) commit(id string, autoCmd *runconfig.Command, comment string)
84 84
 	if id == "" {
85 85
 		cmd := b.Config.Cmd
86 86
 		if runtime.GOOS != "windows" {
87
-			b.Config.Cmd = runconfig.NewCommand("/bin/sh", "-c", "#(nop) "+comment)
87
+			b.Config.Cmd = stringutils.NewStrSlice("/bin/sh", "-c", "#(nop) "+comment)
88 88
 		} else {
89
-			b.Config.Cmd = runconfig.NewCommand("cmd", "/S /C", "REM (nop) "+comment)
89
+			b.Config.Cmd = stringutils.NewStrSlice("cmd", "/S /C", "REM (nop) "+comment)
90 90
 		}
91
-		defer func(cmd *runconfig.Command) { b.Config.Cmd = cmd }(cmd)
91
+		defer func(cmd *stringutils.StrSlice) { b.Config.Cmd = cmd }(cmd)
92 92
 
93 93
 		hit, err := b.probeCache()
94 94
 		if err != nil {
... ...
@@ -215,11 +216,11 @@ func (b *builder) runContextCommand(args []string, allowRemote bool, allowDecomp
215 215
 
216 216
 	cmd := b.Config.Cmd
217 217
 	if runtime.GOOS != "windows" {
218
-		b.Config.Cmd = runconfig.NewCommand("/bin/sh", "-c", fmt.Sprintf("#(nop) %s %s in %s", cmdName, srcHash, dest))
218
+		b.Config.Cmd = stringutils.NewStrSlice("/bin/sh", "-c", fmt.Sprintf("#(nop) %s %s in %s", cmdName, srcHash, dest))
219 219
 	} else {
220
-		b.Config.Cmd = runconfig.NewCommand("cmd", "/S /C", fmt.Sprintf("REM (nop) %s %s in %s", cmdName, srcHash, dest))
220
+		b.Config.Cmd = stringutils.NewStrSlice("cmd", "/S /C", fmt.Sprintf("REM (nop) %s %s in %s", cmdName, srcHash, dest))
221 221
 	}
222
-	defer func(cmd *runconfig.Command) { b.Config.Cmd = cmd }(cmd)
222
+	defer func(cmd *stringutils.StrSlice) { b.Config.Cmd = cmd }(cmd)
223 223
 
224 224
 	hit, err := b.probeCache()
225 225
 	if err != nil {
... ...
@@ -630,7 +631,7 @@ func (b *builder) create() (*daemon.Container, error) {
630 630
 		c.Path = s[0]
631 631
 		c.Args = s[1:]
632 632
 	} else {
633
-		config.Cmd = runconfig.NewCommand()
633
+		config.Cmd = stringutils.NewStrSlice()
634 634
 	}
635 635
 
636 636
 	return c, nil
... ...
@@ -33,6 +33,7 @@ import (
33 33
 	"github.com/docker/docker/pkg/nat"
34 34
 	"github.com/docker/docker/pkg/signal"
35 35
 	"github.com/docker/docker/pkg/stringid"
36
+	"github.com/docker/docker/pkg/stringutils"
36 37
 	"github.com/docker/docker/pkg/sysinfo"
37 38
 	"github.com/docker/docker/pkg/system"
38 39
 	"github.com/docker/docker/pkg/truncindex"
... ...
@@ -437,7 +438,7 @@ func (daemon *Daemon) generateHostname(id string, config *runconfig.Config) {
437 437
 	}
438 438
 }
439 439
 
440
-func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint *runconfig.Entrypoint, configCmd *runconfig.Command) (string, []string) {
440
+func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint *stringutils.StrSlice, configCmd *stringutils.StrSlice) (string, []string) {
441 441
 	var (
442 442
 		entrypoint string
443 443
 		args       []string
... ...
@@ -14,6 +14,7 @@ import (
14 14
 	"github.com/docker/docker/pkg/ioutils"
15 15
 	"github.com/docker/docker/pkg/pools"
16 16
 	"github.com/docker/docker/pkg/stringid"
17
+	"github.com/docker/docker/pkg/stringutils"
17 18
 	"github.com/docker/docker/runconfig"
18 19
 )
19 20
 
... ...
@@ -139,8 +140,8 @@ func (d *Daemon) ContainerExecCreate(config *runconfig.ExecConfig) (string, erro
139 139
 		return "", err
140 140
 	}
141 141
 
142
-	cmd := runconfig.NewCommand(config.Cmd...)
143
-	entrypoint, args := d.getEntrypointAndArgs(runconfig.NewEntrypoint(), cmd)
142
+	cmd := stringutils.NewStrSlice(config.Cmd...)
143
+	entrypoint, args := d.getEntrypointAndArgs(stringutils.NewStrSlice(), cmd)
144 144
 
145 145
 	user := config.User
146 146
 	if len(user) == 0 {
147 147
new file mode 100644
... ...
@@ -0,0 +1,71 @@
0
+package stringutils
1
+
2
+import (
3
+	"encoding/json"
4
+	"strings"
5
+)
6
+
7
+// StrSlice representes a string or an array of strings.
8
+// We need to override the json decoder to accept both options.
9
+type StrSlice struct {
10
+	parts []string
11
+}
12
+
13
+// MarshalJSON Marshals (or serializes) the StrSlice into the json format.
14
+// This method is needed to implement json.Marshaller.
15
+func (e *StrSlice) MarshalJSON() ([]byte, error) {
16
+	if e == nil {
17
+		return []byte{}, nil
18
+	}
19
+	return json.Marshal(e.Slice())
20
+}
21
+
22
+// UnmarshalJSON decodes the byte slice whether it's a string or an array of strings.
23
+// This method is needed to implement json.Unmarshaler.
24
+func (e *StrSlice) UnmarshalJSON(b []byte) error {
25
+	if len(b) == 0 {
26
+		return nil
27
+	}
28
+
29
+	p := make([]string, 0, 1)
30
+	if err := json.Unmarshal(b, &p); err != nil {
31
+		var s string
32
+		if err := json.Unmarshal(b, &s); err != nil {
33
+			return err
34
+		}
35
+		p = append(p, s)
36
+	}
37
+
38
+	e.parts = p
39
+	return nil
40
+}
41
+
42
+// Len returns the number of parts of the StrSlice.
43
+func (e *StrSlice) Len() int {
44
+	if e == nil {
45
+		return 0
46
+	}
47
+	return len(e.parts)
48
+}
49
+
50
+// Slice gets the parts of the StrSlice as a Slice of string.
51
+func (e *StrSlice) Slice() []string {
52
+	if e == nil {
53
+		return nil
54
+	}
55
+	return e.parts
56
+}
57
+
58
+// ToString gets space separated string of all the parts.
59
+func (e *StrSlice) ToString() string {
60
+	s := e.Slice()
61
+	if s == nil {
62
+		return ""
63
+	}
64
+	return strings.Join(s, " ")
65
+}
66
+
67
+// NewStrSlice creates an StrSlice based on the specified parts (as strings).
68
+func NewStrSlice(parts ...string) *StrSlice {
69
+	return &StrSlice{parts}
70
+}
0 71
new file mode 100644
... ...
@@ -0,0 +1,105 @@
0
+package stringutils
1
+
2
+import (
3
+	"encoding/json"
4
+	"testing"
5
+)
6
+
7
+func TestStrSliceMarshalJSON(t *testing.T) {
8
+	strss := map[*StrSlice]string{
9
+		nil:         "",
10
+		&StrSlice{}: "null",
11
+		&StrSlice{[]string{"/bin/sh", "-c", "echo"}}: `["/bin/sh","-c","echo"]`,
12
+	}
13
+
14
+	for strs, expected := range strss {
15
+		data, err := strs.MarshalJSON()
16
+		if err != nil {
17
+			t.Fatal(err)
18
+		}
19
+		if string(data) != expected {
20
+			t.Fatalf("Expected %v, got %v", expected, string(data))
21
+		}
22
+	}
23
+}
24
+
25
+func TestStrSliceUnmarshalJSON(t *testing.T) {
26
+	parts := map[string][]string{
27
+		"":   {"default", "values"},
28
+		"[]": {},
29
+		`["/bin/sh","-c","echo"]`: {"/bin/sh", "-c", "echo"},
30
+	}
31
+	for json, expectedParts := range parts {
32
+		strs := &StrSlice{
33
+			[]string{"default", "values"},
34
+		}
35
+		if err := strs.UnmarshalJSON([]byte(json)); err != nil {
36
+			t.Fatal(err)
37
+		}
38
+
39
+		actualParts := strs.Slice()
40
+		if len(actualParts) != len(expectedParts) {
41
+			t.Fatalf("Expected %v parts, got %v (%v)", len(expectedParts), len(actualParts), expectedParts)
42
+		}
43
+		for index, part := range actualParts {
44
+			if part != expectedParts[index] {
45
+				t.Fatalf("Expected %v, got %v", expectedParts, actualParts)
46
+				break
47
+			}
48
+		}
49
+	}
50
+}
51
+
52
+func TestStrSliceUnmarshalString(t *testing.T) {
53
+	var e *StrSlice
54
+	echo, err := json.Marshal("echo")
55
+	if err != nil {
56
+		t.Fatal(err)
57
+	}
58
+	if err := json.Unmarshal(echo, &e); err != nil {
59
+		t.Fatal(err)
60
+	}
61
+
62
+	slice := e.Slice()
63
+	if len(slice) != 1 {
64
+		t.Fatalf("expected 1 element after unmarshal: %q", slice)
65
+	}
66
+
67
+	if slice[0] != "echo" {
68
+		t.Fatalf("expected `echo`, got: %q", slice[0])
69
+	}
70
+}
71
+
72
+func TestStrSliceUnmarshalSlice(t *testing.T) {
73
+	var e *StrSlice
74
+	echo, err := json.Marshal([]string{"echo"})
75
+	if err != nil {
76
+		t.Fatal(err)
77
+	}
78
+	if err := json.Unmarshal(echo, &e); err != nil {
79
+		t.Fatal(err)
80
+	}
81
+
82
+	slice := e.Slice()
83
+	if len(slice) != 1 {
84
+		t.Fatalf("expected 1 element after unmarshal: %q", slice)
85
+	}
86
+
87
+	if slice[0] != "echo" {
88
+		t.Fatalf("expected `echo`, got: %q", slice[0])
89
+	}
90
+}
91
+
92
+func TestStrSliceToString(t *testing.T) {
93
+	slices := map[*StrSlice]string{
94
+		NewStrSlice(""):           "",
95
+		NewStrSlice("one"):        "one",
96
+		NewStrSlice("one", "two"): "one two",
97
+	}
98
+	for s, expected := range slices {
99
+		toString := s.ToString()
100
+		if toString != expected {
101
+			t.Fatalf("Expected %v, got %v", expected, toString)
102
+		}
103
+	}
104
+}
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"testing"
5 5
 
6 6
 	"github.com/docker/docker/pkg/nat"
7
+	"github.com/docker/docker/pkg/stringutils"
7 8
 )
8 9
 
9 10
 // Just to make life easier
... ...
@@ -32,12 +33,12 @@ func TestCompare(t *testing.T) {
32 32
 	volumes3["/test3"] = struct{}{}
33 33
 	envs1 := []string{"ENV1=value1", "ENV2=value2"}
34 34
 	envs2 := []string{"ENV1=value1", "ENV3=value3"}
35
-	entrypoint1 := &Entrypoint{parts: []string{"/bin/sh", "-c"}}
36
-	entrypoint2 := &Entrypoint{parts: []string{"/bin/sh", "-d"}}
37
-	entrypoint3 := &Entrypoint{parts: []string{"/bin/sh", "-c", "echo"}}
38
-	cmd1 := &Command{parts: []string{"/bin/sh", "-c"}}
39
-	cmd2 := &Command{parts: []string{"/bin/sh", "-d"}}
40
-	cmd3 := &Command{parts: []string{"/bin/sh", "-c", "echo"}}
35
+	entrypoint1 := stringutils.NewStrSlice("/bin/sh", "-c")
36
+	entrypoint2 := stringutils.NewStrSlice("/bin/sh", "-d")
37
+	entrypoint3 := stringutils.NewStrSlice("/bin/sh", "-c", "echo")
38
+	cmd1 := stringutils.NewStrSlice("/bin/sh", "-c")
39
+	cmd2 := stringutils.NewStrSlice("/bin/sh", "-d")
40
+	cmd3 := stringutils.NewStrSlice("/bin/sh", "-c", "echo")
41 41
 	labels1 := map[string]string{"LABEL1": "value1", "LABEL2": "value2"}
42 42
 	labels2 := map[string]string{"LABEL1": "value1", "LABEL2": "value3"}
43 43
 	labels3 := map[string]string{"LABEL1": "value1", "LABEL2": "value2", "LABEL3": "value3"}
... ...
@@ -3,132 +3,11 @@ package runconfig
3 3
 import (
4 4
 	"encoding/json"
5 5
 	"io"
6
-	"strings"
7 6
 
8 7
 	"github.com/docker/docker/pkg/nat"
8
+	"github.com/docker/docker/pkg/stringutils"
9 9
 )
10 10
 
11
-// Entrypoint encapsulates the container entrypoint.
12
-// It might be represented as a string or an array of strings.
13
-// We need to override the json decoder to accept both options.
14
-// The JSON decoder will fail if the api sends an string and
15
-//  we try to decode it into an array of string.
16
-type Entrypoint struct {
17
-	parts []string
18
-}
19
-
20
-// MarshalJSON Marshals (or serializes) the Entrypoint into the json format.
21
-// This method is needed to implement json.Marshaller.
22
-func (e *Entrypoint) MarshalJSON() ([]byte, error) {
23
-	if e == nil {
24
-		return []byte{}, nil
25
-	}
26
-	return json.Marshal(e.Slice())
27
-}
28
-
29
-// UnmarshalJSON decodes the entrypoint whether it's a string or an array of strings.
30
-// This method is needed to implement json.Unmarshaler.
31
-func (e *Entrypoint) UnmarshalJSON(b []byte) error {
32
-	if len(b) == 0 {
33
-		return nil
34
-	}
35
-
36
-	p := make([]string, 0, 1)
37
-	if err := json.Unmarshal(b, &p); err != nil {
38
-		var s string
39
-		if err := json.Unmarshal(b, &s); err != nil {
40
-			return err
41
-		}
42
-		p = append(p, s)
43
-	}
44
-	e.parts = p
45
-	return nil
46
-}
47
-
48
-// Len returns the number of parts of the Entrypoint.
49
-func (e *Entrypoint) Len() int {
50
-	if e == nil {
51
-		return 0
52
-	}
53
-	return len(e.parts)
54
-}
55
-
56
-// Slice gets the parts of the Entrypoint as a Slice of string.
57
-func (e *Entrypoint) Slice() []string {
58
-	if e == nil {
59
-		return nil
60
-	}
61
-	return e.parts
62
-}
63
-
64
-// NewEntrypoint creates an Entrypoint based on the specified parts (as strings).
65
-func NewEntrypoint(parts ...string) *Entrypoint {
66
-	return &Entrypoint{parts}
67
-}
68
-
69
-// Command encapsulates the container command.
70
-// It might be represented as a string or an array of strings.
71
-// We need to override the json decoder to accept both options.
72
-// The JSON decoder will fail if the api sends an string and
73
-//  we try to decode it into an array of string.
74
-type Command struct {
75
-	parts []string
76
-}
77
-
78
-// ToString gets a string representing a Command.
79
-func (e *Command) ToString() string {
80
-	return strings.Join(e.parts, " ")
81
-}
82
-
83
-// MarshalJSON Marshals (or serializes) the Command into the json format.
84
-// This method is needed to implement json.Marshaller.
85
-func (e *Command) MarshalJSON() ([]byte, error) {
86
-	if e == nil {
87
-		return []byte{}, nil
88
-	}
89
-	return json.Marshal(e.Slice())
90
-}
91
-
92
-// UnmarshalJSON decodes the entrypoint whether it's a string or an array of strings.
93
-// This method is needed to implement json.Unmarshaler.
94
-func (e *Command) UnmarshalJSON(b []byte) error {
95
-	if len(b) == 0 {
96
-		return nil
97
-	}
98
-
99
-	p := make([]string, 0, 1)
100
-	if err := json.Unmarshal(b, &p); err != nil {
101
-		var s string
102
-		if err := json.Unmarshal(b, &s); err != nil {
103
-			return err
104
-		}
105
-		p = append(p, s)
106
-	}
107
-	e.parts = p
108
-	return nil
109
-}
110
-
111
-// Len returns the number of parts of the Entrypoint.
112
-func (e *Command) Len() int {
113
-	if e == nil {
114
-		return 0
115
-	}
116
-	return len(e.parts)
117
-}
118
-
119
-// Slice gets the parts of the Entrypoint as a Slice of string.
120
-func (e *Command) Slice() []string {
121
-	if e == nil {
122
-		return nil
123
-	}
124
-	return e.parts
125
-}
126
-
127
-// NewCommand creates a Command based on the specified parts (as strings).
128
-func NewCommand(parts ...string) *Command {
129
-	return &Command{parts}
130
-}
131
-
132 11
 // Config contains the configuration data about a container.
133 12
 // It should hold only portable information about the container.
134 13
 // Here, "portable" means "independent from the host we are running on".
... ...
@@ -146,12 +25,12 @@ type Config struct {
146 146
 	OpenStdin       bool                  // Open stdin
147 147
 	StdinOnce       bool                  // If true, close stdin after the 1 attached client disconnects.
148 148
 	Env             []string              // List of environment variable to set in the container
149
-	Cmd             *Command              // Command to run when starting the container
149
+	Cmd             *stringutils.StrSlice // Command to run when starting the container
150 150
 	Image           string                // Name of the image as it was passed by the operator (eg. could be symbolic)
151 151
 	Volumes         map[string]struct{}   // List of volumes (mounts) used for the container
152 152
 	VolumeDriver    string                // Name of the volume driver used to mount volumes
153 153
 	WorkingDir      string                // Current directory (PWD) in the command will be launched
154
-	Entrypoint      *Entrypoint           // Entrypoint to run when starting the container
154
+	Entrypoint      *stringutils.StrSlice // Entrypoint to run when starting the container
155 155
 	NetworkDisabled bool                  // Is network disabled
156 156
 	MacAddress      string                // Mac Address of the container
157 157
 	OnBuild         []string              // ONBUILD metadata that were defined on the image Dockerfile
... ...
@@ -2,124 +2,21 @@ package runconfig
2 2
 
3 3
 import (
4 4
 	"bytes"
5
-	"encoding/json"
6 5
 	"fmt"
7 6
 	"io/ioutil"
8 7
 	"testing"
9
-)
10
-
11
-func TestEntrypointMarshalJSON(t *testing.T) {
12
-	entrypoints := map[*Entrypoint]string{
13
-		nil:                                            "",
14
-		&Entrypoint{}:                                  "null",
15
-		&Entrypoint{[]string{"/bin/sh", "-c", "echo"}}: `["/bin/sh","-c","echo"]`,
16
-	}
17
-
18
-	for entrypoint, expected := range entrypoints {
19
-		data, err := entrypoint.MarshalJSON()
20
-		if err != nil {
21
-			t.Fatal(err)
22
-		}
23
-		if string(data) != expected {
24
-			t.Fatalf("Expected %v, got %v", expected, string(data))
25
-		}
26
-	}
27
-}
28
-
29
-func TestEntrypointUnmarshalJSON(t *testing.T) {
30
-	parts := map[string][]string{
31
-		"":   {"default", "values"},
32
-		"[]": {},
33
-		`["/bin/sh","-c","echo"]`: {"/bin/sh", "-c", "echo"},
34
-	}
35
-	for json, expectedParts := range parts {
36
-		entrypoint := &Entrypoint{
37
-			[]string{"default", "values"},
38
-		}
39
-		if err := entrypoint.UnmarshalJSON([]byte(json)); err != nil {
40
-			t.Fatal(err)
41
-		}
42
-
43
-		actualParts := entrypoint.Slice()
44
-		if len(actualParts) != len(expectedParts) {
45
-			t.Fatalf("Expected %v parts, got %v (%v)", len(expectedParts), len(actualParts), expectedParts)
46
-		}
47
-		for index, part := range actualParts {
48
-			if part != expectedParts[index] {
49
-				t.Fatalf("Expected %v, got %v", expectedParts, actualParts)
50
-				break
51
-			}
52
-		}
53
-	}
54
-}
55
-
56
-func TestCommandToString(t *testing.T) {
57
-	commands := map[*Command]string{
58
-		&Command{[]string{""}}:           "",
59
-		&Command{[]string{"one"}}:        "one",
60
-		&Command{[]string{"one", "two"}}: "one two",
61
-	}
62
-	for command, expected := range commands {
63
-		toString := command.ToString()
64
-		if toString != expected {
65
-			t.Fatalf("Expected %v, got %v", expected, toString)
66
-		}
67
-	}
68
-}
69
-
70
-func TestCommandMarshalJSON(t *testing.T) {
71
-	commands := map[*Command]string{
72
-		nil:        "",
73
-		&Command{}: "null",
74
-		&Command{[]string{"/bin/sh", "-c", "echo"}}: `["/bin/sh","-c","echo"]`,
75
-	}
76
-
77
-	for command, expected := range commands {
78
-		data, err := command.MarshalJSON()
79
-		if err != nil {
80
-			t.Fatal(err)
81
-		}
82
-		if string(data) != expected {
83
-			t.Fatalf("Expected %v, got %v", expected, string(data))
84
-		}
85
-	}
86
-}
87
-
88
-func TestCommandUnmarshalJSON(t *testing.T) {
89
-	parts := map[string][]string{
90
-		"":   {"default", "values"},
91
-		"[]": {},
92
-		`["/bin/sh","-c","echo"]`: {"/bin/sh", "-c", "echo"},
93
-	}
94
-	for json, expectedParts := range parts {
95
-		command := &Command{
96
-			[]string{"default", "values"},
97
-		}
98
-		if err := command.UnmarshalJSON([]byte(json)); err != nil {
99
-			t.Fatal(err)
100
-		}
101 8
 
102
-		actualParts := command.Slice()
103
-		if len(actualParts) != len(expectedParts) {
104
-			t.Fatalf("Expected %v parts, got %v (%v)", len(expectedParts), len(actualParts), expectedParts)
105
-		}
106
-		for index, part := range actualParts {
107
-			if part != expectedParts[index] {
108
-				t.Fatalf("Expected %v, got %v", expectedParts, actualParts)
109
-				break
110
-			}
111
-		}
112
-	}
113
-}
9
+	"github.com/docker/docker/pkg/stringutils"
10
+)
114 11
 
115 12
 func TestDecodeContainerConfig(t *testing.T) {
116 13
 	fixtures := []struct {
117 14
 		file       string
118
-		entrypoint *Entrypoint
15
+		entrypoint *stringutils.StrSlice
119 16
 	}{
120
-		{"fixtures/container_config_1_14.json", NewEntrypoint()},
121
-		{"fixtures/container_config_1_17.json", NewEntrypoint("bash")},
122
-		{"fixtures/container_config_1_19.json", NewEntrypoint("bash")},
17
+		{"fixtures/container_config_1_14.json", stringutils.NewStrSlice()},
18
+		{"fixtures/container_config_1_17.json", stringutils.NewStrSlice("bash")},
19
+		{"fixtures/container_config_1_19.json", stringutils.NewStrSlice("bash")},
123 20
 	}
124 21
 
125 22
 	for _, f := range fixtures {
... ...
@@ -146,83 +43,3 @@ func TestDecodeContainerConfig(t *testing.T) {
146 146
 		}
147 147
 	}
148 148
 }
149
-
150
-func TestEntrypointUnmarshalString(t *testing.T) {
151
-	var e *Entrypoint
152
-	echo, err := json.Marshal("echo")
153
-	if err != nil {
154
-		t.Fatal(err)
155
-	}
156
-	if err := json.Unmarshal(echo, &e); err != nil {
157
-		t.Fatal(err)
158
-	}
159
-
160
-	slice := e.Slice()
161
-	if len(slice) != 1 {
162
-		t.Fatalf("expected 1 element after unmarshal: %q", slice)
163
-	}
164
-
165
-	if slice[0] != "echo" {
166
-		t.Fatalf("expected `echo`, got: %q", slice[0])
167
-	}
168
-}
169
-
170
-func TestEntrypointUnmarshalSlice(t *testing.T) {
171
-	var e *Entrypoint
172
-	echo, err := json.Marshal([]string{"echo"})
173
-	if err != nil {
174
-		t.Fatal(err)
175
-	}
176
-	if err := json.Unmarshal(echo, &e); err != nil {
177
-		t.Fatal(err)
178
-	}
179
-
180
-	slice := e.Slice()
181
-	if len(slice) != 1 {
182
-		t.Fatalf("expected 1 element after unmarshal: %q", slice)
183
-	}
184
-
185
-	if slice[0] != "echo" {
186
-		t.Fatalf("expected `echo`, got: %q", slice[0])
187
-	}
188
-}
189
-
190
-func TestCommandUnmarshalSlice(t *testing.T) {
191
-	var e *Command
192
-	echo, err := json.Marshal([]string{"echo"})
193
-	if err != nil {
194
-		t.Fatal(err)
195
-	}
196
-	if err := json.Unmarshal(echo, &e); err != nil {
197
-		t.Fatal(err)
198
-	}
199
-
200
-	slice := e.Slice()
201
-	if len(slice) != 1 {
202
-		t.Fatalf("expected 1 element after unmarshal: %q", slice)
203
-	}
204
-
205
-	if slice[0] != "echo" {
206
-		t.Fatalf("expected `echo`, got: %q", slice[0])
207
-	}
208
-}
209
-
210
-func TestCommandUnmarshalString(t *testing.T) {
211
-	var e *Command
212
-	echo, err := json.Marshal("echo")
213
-	if err != nil {
214
-		t.Fatal(err)
215
-	}
216
-	if err := json.Unmarshal(echo, &e); err != nil {
217
-		t.Fatal(err)
218
-	}
219
-
220
-	slice := e.Slice()
221
-	if len(slice) != 1 {
222
-		t.Fatalf("expected 1 element after unmarshal: %q", slice)
223
-	}
224
-
225
-	if slice[0] != "echo" {
226
-		t.Fatalf("expected `echo`, got: %q", slice[0])
227
-	}
228
-}
... ...
@@ -9,6 +9,7 @@ import (
9 9
 	flag "github.com/docker/docker/pkg/mflag"
10 10
 	"github.com/docker/docker/pkg/nat"
11 11
 	"github.com/docker/docker/pkg/parsers"
12
+	"github.com/docker/docker/pkg/stringutils"
12 13
 	"github.com/docker/docker/pkg/units"
13 14
 )
14 15
 
... ...
@@ -199,15 +200,15 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
199 199
 
200 200
 	var (
201 201
 		parsedArgs = cmd.Args()
202
-		runCmd     *Command
203
-		entrypoint *Entrypoint
202
+		runCmd     *stringutils.StrSlice
203
+		entrypoint *stringutils.StrSlice
204 204
 		image      = cmd.Arg(0)
205 205
 	)
206 206
 	if len(parsedArgs) > 1 {
207
-		runCmd = NewCommand(parsedArgs[1:]...)
207
+		runCmd = stringutils.NewStrSlice(parsedArgs[1:]...)
208 208
 	}
209 209
 	if *flEntrypoint != "" {
210
-		entrypoint = NewEntrypoint(*flEntrypoint)
210
+		entrypoint = stringutils.NewStrSlice(*flEntrypoint)
211 211
 	}
212 212
 
213 213
 	lc, err := parseKeyValueOpts(flLxcOpts)
... ...
@@ -486,7 +486,7 @@ func TestParseEntryPoint(t *testing.T) {
486 486
 	if err != nil {
487 487
 		t.Fatal(err)
488 488
 	}
489
-	if config.Entrypoint.Len() != 1 && config.Entrypoint.parts[0] != "anything" {
489
+	if config.Entrypoint.Len() != 1 && config.Entrypoint.Slice()[0] != "anything" {
490 490
 		t.Fatalf("Expected entrypoint 'anything', got %v", config.Entrypoint)
491 491
 	}
492 492
 }