@@ -7,26 +7,64 @@ import (
7
7
"os"
8
8
"path/filepath"
9
9
10
- "github.com/docker/cli/cli/compose/loader"
11
-
12
- "github.com/docker/app/specification"
13
- "github.com/docker/cli/cli/compose/schema"
14
-
15
10
"github.com/docker/app/internal"
11
+ "github.com/docker/app/specification"
16
12
"github.com/docker/app/types"
13
+ "github.com/docker/cli/cli/compose/loader"
14
+ "github.com/docker/cli/cli/compose/schema"
17
15
"github.com/docker/docker/pkg/archive"
18
16
"github.com/pkg/errors"
19
17
)
20
18
19
+ var (
20
+ crlf = []byte {'\r' , '\n' }
21
+ lf = []byte {'\n' }
22
+ delimiters = [][]byte {
23
+ []byte ("\r \n ---\r \n " ),
24
+ []byte ("\n ---\r \n " ),
25
+ []byte ("\r \n ---\n " ),
26
+ []byte ("\n ---\n " ),
27
+ }
28
+ )
29
+
30
+ // useCRLF detects which line break should be used
31
+ func useCRLF (data []byte ) bool {
32
+ nbCrlf := bytes .Count (data , crlf )
33
+ nbLf := bytes .Count (data , lf )
34
+ switch {
35
+ case nbCrlf == nbLf :
36
+ // document contains only CRLF
37
+ return true
38
+ case nbCrlf == 0 :
39
+ // document does not contain any CRLF
40
+ return false
41
+ default :
42
+ // document contains mixed line breaks, so use the OS default
43
+ return bytes .Equal (defaultLineBreak , crlf )
44
+ }
45
+ }
46
+
47
+ // splitSingleFile split a multidocument using all possible document delimiters
48
+ func splitSingleFile (data []byte ) [][]byte {
49
+ parts := [][]byte {data }
50
+ for _ , delimiter := range delimiters {
51
+ var intermediate [][]byte
52
+ for _ , part := range parts {
53
+ intermediate = append (intermediate , bytes .Split (part , delimiter )... )
54
+ }
55
+ parts = intermediate
56
+ }
57
+ return parts
58
+ }
59
+
21
60
// LoadFromSingleFile loads a docker app from a single-file format (as a reader)
22
61
func LoadFromSingleFile (path string , r io.Reader , ops ... func (* types.App ) error ) (* types.App , error ) {
23
62
data , err := ioutil .ReadAll (r )
24
63
if err != nil {
25
64
return nil , errors .Wrap (err , "error reading single-file" )
26
65
}
27
- hasCRLF := bytes .Contains (data , []byte {'\r' , '\n' })
28
66
29
- parts := bytes . Split (data , types . YamlSingleFileSeparator ( hasCRLF ) )
67
+ parts := splitSingleFile (data )
30
68
if len (parts ) != 3 {
31
69
return nil , errors .Errorf ("malformed single-file application: expected 3 documents, got %d" , len (parts ))
32
70
}
@@ -51,11 +89,12 @@ func LoadFromSingleFile(path string, r io.Reader, ops ...func(*types.App) error)
51
89
return nil , errors .New ("malformed single-file application" )
52
90
}
53
91
}
92
+
54
93
appOps := append ([]func (* types.App ) error {
55
94
types .WithComposes (compose ),
56
95
types .WithParameters (params ),
57
96
types .Metadata (metadata ),
58
- types .WithCRLF (hasCRLF ),
97
+ types .WithCRLF (useCRLF ( data ) ),
59
98
}, ops ... )
60
99
return types .NewApp (path , appOps ... )
61
100
}
0 commit comments