1package archive // import "github.com/docker/docker/pkg/archive" 2 3import ( 4 "archive/tar" 5 "bytes" 6 "io" 7) 8 9// Generate generates a new archive from the content provided 10// as input. 11// 12// `files` is a sequence of path/content pairs. A new file is 13// added to the archive for each pair. 14// If the last pair is incomplete, the file is created with an 15// empty content. For example: 16// 17// Generate("foo.txt", "hello world", "emptyfile") 18// 19// The above call will return an archive with 2 files: 20// * ./foo.txt with content "hello world" 21// * ./empty with empty content 22// 23// FIXME: stream content instead of buffering 24// FIXME: specify permissions and other archive metadata 25func Generate(input ...string) (io.Reader, error) { 26 files := parseStringPairs(input...) 27 buf := new(bytes.Buffer) 28 tw := tar.NewWriter(buf) 29 for _, file := range files { 30 name, content := file[0], file[1] 31 hdr := &tar.Header{ 32 Name: name, 33 Size: int64(len(content)), 34 } 35 if err := tw.WriteHeader(hdr); err != nil { 36 return nil, err 37 } 38 if _, err := tw.Write([]byte(content)); err != nil { 39 return nil, err 40 } 41 } 42 if err := tw.Close(); err != nil { 43 return nil, err 44 } 45 return buf, nil 46} 47 48func parseStringPairs(input ...string) (output [][2]string) { 49 output = make([][2]string, 0, len(input)/2+1) 50 for i := 0; i < len(input); i += 2 { 51 var pair [2]string 52 pair[0] = input[i] 53 if i+1 < len(input) { 54 pair[1] = input[i+1] 55 } 56 output = append(output, pair) 57 } 58 return 59} 60