blob: 60017aa94a4c8d2c97b59734f2125e4116dbd220 [file] [log] [blame]
Jeff Gaston11b5c512017-10-12 12:19:14 -07001// Copyright 2015 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package main
16
17import (
18 "bytes"
19 "flag"
20 "fmt"
21 "io"
22 "io/ioutil"
23 "os"
24 "path/filepath"
25 "runtime"
26 "strings"
27
28 "android/soong/zip"
29)
30
31type byteReaderCloser struct {
32 *bytes.Reader
33 io.Closer
34}
35
36type pathMapping struct {
37 dest, src string
38 zipMethod uint16
39}
40
41type uniqueSet map[string]bool
42
43func (u *uniqueSet) String() string {
44 return `""`
45}
46
47func (u *uniqueSet) Set(s string) error {
48 if _, found := (*u)[s]; found {
49 return fmt.Errorf("File %q was specified twice as a file to not deflate", s)
50 } else {
51 (*u)[s] = true
52 }
53
54 return nil
55}
56
57type file struct{}
58
59type listFiles struct{}
60
61type dir struct{}
62
63func (f *file) String() string {
64 return `""`
65}
66
67func (f *file) Set(s string) error {
68 if *relativeRoot == "" {
69 return fmt.Errorf("must pass -C before -f")
70 }
71
72 fArgs = append(fArgs, zip.FileArg{
73 PathPrefixInZip: filepath.Clean(*rootPrefix),
74 SourcePrefixToStrip: filepath.Clean(*relativeRoot),
75 SourceFiles: []string{s},
76 })
77
78 return nil
79}
80
81func (l *listFiles) String() string {
82 return `""`
83}
84
85func (l *listFiles) Set(s string) error {
86 if *relativeRoot == "" {
87 return fmt.Errorf("must pass -C before -l")
88 }
89
90 list, err := ioutil.ReadFile(s)
91 if err != nil {
92 return err
93 }
94
95 fArgs = append(fArgs, zip.FileArg{
96 PathPrefixInZip: filepath.Clean(*rootPrefix),
97 SourcePrefixToStrip: filepath.Clean(*relativeRoot),
98 SourceFiles: strings.Split(string(list), "\n"),
99 })
100
101 return nil
102}
103
104func (d *dir) String() string {
105 return `""`
106}
107
108func (d *dir) Set(s string) error {
109 if *relativeRoot == "" {
110 return fmt.Errorf("must pass -C before -D")
111 }
112
113 fArgs = append(fArgs, zip.FileArg{
114 PathPrefixInZip: filepath.Clean(*rootPrefix),
115 SourcePrefixToStrip: filepath.Clean(*relativeRoot),
116 GlobDir: filepath.Clean(s),
117 })
118
119 return nil
120}
121
122var (
Nan Zhang674dd932018-01-26 18:30:36 -0800123 rootPrefix, relativeRoot *string
Jeff Gaston11b5c512017-10-12 12:19:14 -0700124
125 fArgs zip.FileArgs
126 nonDeflatedFiles = make(uniqueSet)
Jeff Gaston11b5c512017-10-12 12:19:14 -0700127)
128
Jeff Gaston11b5c512017-10-12 12:19:14 -0700129func usage() {
130 fmt.Fprintf(os.Stderr, "usage: zip -o zipfile [-m manifest] -C dir [-f|-l file]...\n")
131 flag.PrintDefaults()
132 os.Exit(2)
133}
134
135func main() {
Nan Zhang674dd932018-01-26 18:30:36 -0800136 var expandedArgs []string
137 for _, arg := range os.Args {
138 if strings.HasPrefix(arg, "@") {
139 bytes, err := ioutil.ReadFile(strings.TrimPrefix(arg, "@"))
140 if err != nil {
141 fmt.Fprintln(os.Stderr, err.Error())
142 os.Exit(1)
143 }
144 respArgs := zip.ReadRespFile(bytes)
145 expandedArgs = append(expandedArgs, respArgs...)
146 } else {
147 expandedArgs = append(expandedArgs, arg)
148 }
149 }
150
151 flags := flag.NewFlagSet("flags", flag.ExitOnError)
152
153 out := flags.String("o", "", "file to write zip file to")
154 manifest := flags.String("m", "", "input jar manifest file name")
155 directories := flags.Bool("d", false, "include directories in zip")
156 rootPrefix = flags.String("P", "", "path prefix within the zip at which to place files")
157 relativeRoot = flags.String("C", "", "path to use as relative root of files in following -f, -l, or -D arguments")
158 parallelJobs := flags.Int("j", runtime.NumCPU(), "number of parallel threads to use")
159 compLevel := flags.Int("L", 5, "deflate compression level (0-9)")
160 emulateJar := flags.Bool("jar", false, "modify the resultant .zip to emulate the output of 'jar'")
161 writeIfChanged := flags.Bool("write_if_changed", false, "only update resultant .zip if it has changed")
162
163 cpuProfile := flags.String("cpuprofile", "", "write cpu profile to file")
164 traceFile := flags.String("trace", "", "write trace to file")
165
166 flags.Var(&listFiles{}, "l", "file containing list of .class files")
167 flags.Var(&dir{}, "D", "directory to include in zip")
168 flags.Var(&file{}, "f", "file to include in zip")
169 flags.Var(&nonDeflatedFiles, "s", "file path to be stored within the zip without compression")
170
171 flags.Parse(expandedArgs[1:])
Jeff Gaston11b5c512017-10-12 12:19:14 -0700172
173 err := zip.Run(zip.ZipArgs{
174 FileArgs: fArgs,
175 OutputFilePath: *out,
176 CpuProfileFilePath: *cpuProfile,
177 TraceFilePath: *traceFile,
178 EmulateJar: *emulateJar,
179 AddDirectoryEntriesToZip: *directories,
180 CompressionLevel: *compLevel,
181 ManifestSourcePath: *manifest,
182 NumParallelJobs: *parallelJobs,
183 NonDeflatedFiles: nonDeflatedFiles,
Colin Crossf83c1502017-11-10 13:11:02 -0800184 WriteIfChanged: *writeIfChanged,
Jeff Gaston11b5c512017-10-12 12:19:14 -0700185 })
186 if err != nil {
187 fmt.Fprintln(os.Stderr, err.Error())
188 os.Exit(1)
189 }
190}