@@ -4,6 +4,8 @@ package zip
44import (
55 "bytes"
66 "context"
7+ "io/ioutil"
8+ "os"
79 "os/exec"
810 "path/filepath"
911
@@ -15,6 +17,12 @@ type Options struct {
1517 // Files to add to the zip package.
1618 Files []string
1719
20+ // Root is the directory to use as the root of the zip file. This can
21+ // optionally be set to specify additional files that you want within
22+ // the zip. If this isn't set, we'll create a root with the files specified
23+ // in Files.
24+ Root string
25+
1826 // OutputPath is the path where the zip file will be written. The directory
1927 // containing this path must already exist. If a file already exist here
2028 // it will be overwritten.
@@ -28,6 +36,23 @@ type Options struct {
2836 BaseCmd * exec.Cmd
2937}
3038
39+ func dittoCmd (ctx context.Context , cmd * exec.Cmd ) (* exec.Cmd , error ) {
40+ path , err := exec .LookPath ("ditto" )
41+ if err != nil {
42+ return nil , err
43+ }
44+
45+ // We only set the path if it isn't set. This lets the options set the
46+ // path to the codesigning binary that we use.
47+ if cmd == nil {
48+ cmd = exec .CommandContext (ctx , path )
49+ } else if cmd .Path == "" {
50+ cmd .Path = path
51+ }
52+
53+ return cmd , nil
54+ }
55+
3156// Zip creates a zip archive for notarization using the options given.
3257//
3358// For now this works by subprocessing to "ditto" which is the recommended
@@ -40,28 +65,74 @@ func Zip(ctx context.Context, opts *Options) error {
4065 logger = hclog .NewNullLogger ()
4166 }
4267
43- // Build our command
44- var cmd exec.Cmd
45- if opts .BaseCmd != nil {
46- cmd = * opts .BaseCmd
47- }
48-
49- // We only set the path if it isn't set. This lets the options set the
50- // path to the codesigning binary that we use.
51- if cmd .Path == "" {
52- path , err := exec .LookPath ("ditto" )
68+ // Set our root directory. If one wasn't specified, we create an empty
69+ // temporary directory to act as our root and we copy over the source files
70+ root := opts .Root
71+ if root == "" {
72+ var td string
73+ var err error
74+ td , err = ioutil .TempDir ("" , "gon-createzip" )
5375 if err != nil {
5476 return err
5577 }
56- cmd .Path = path
78+ defer os .RemoveAll (td )
79+ root = td
80+
81+ // Build our copy command
82+ var cmd * exec.Cmd
83+ if opts .BaseCmd != nil {
84+ cmdCopy := * opts .BaseCmd
85+ cmd = & cmdCopy
86+ }
87+ if cmd , err = dittoCmd (ctx , cmd ); err != nil {
88+ return err
89+ }
90+
91+ cmd .Args = []string {
92+ filepath .Base (cmd .Path ),
93+ }
94+ cmd .Args = append (cmd .Args , opts .Files ... )
95+ cmd .Args = append (cmd .Args , root )
96+
97+ // We store all output in out for logging and in case there is an error
98+ var out bytes.Buffer
99+ cmd .Stdout = & out
100+ cmd .Stderr = cmd .Stdout
101+
102+ // Log what we're going to execute
103+ logger .Info ("executing ditto to copy files for archiving" ,
104+ "output_path" , opts .OutputPath ,
105+ "command_path" , cmd .Path ,
106+ "command_args" , cmd .Args ,
107+ )
108+
109+ // Execute copy
110+ if err = cmd .Run (); err != nil {
111+ logger .Error (
112+ "error copying source files to create zip archive" ,
113+ "err" , err ,
114+ "output" , out .String (),
115+ )
116+ return err
117+ }
118+ }
119+
120+ var cmd * exec.Cmd
121+ var err error
122+ if opts .BaseCmd != nil {
123+ cmdCopy := * opts .BaseCmd
124+ cmd = & cmdCopy
125+ }
126+ if cmd , err = dittoCmd (ctx , cmd ); err != nil {
127+ return err
57128 }
58129
59130 cmd .Args = []string {
60131 filepath .Base (cmd .Path ),
61132 "-c" , // create an archive
62133 "-k" , // create a PKZip archive, not CPIO
63134 }
64- cmd .Args = append (cmd .Args , opts . Files ... )
135+ cmd .Args = append (cmd .Args , root )
65136 cmd .Args = append (cmd .Args , opts .OutputPath )
66137
67138 // We store all output in out for logging and in case there is an error
@@ -77,7 +148,7 @@ func Zip(ctx context.Context, opts *Options) error {
77148 )
78149
79150 // Execute
80- if err : = cmd .Run (); err != nil {
151+ if err = cmd .Run (); err != nil {
81152 logger .Error ("error creating zip archive" , "err" , err , "output" , out .String ())
82153 return err
83154 }
0 commit comments