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