Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3bb5f2f2 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Add Respfile support for soong_zip."

parents 1fd46878 674dd932
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -123,8 +123,10 @@ var (

	jar = pctx.AndroidStaticRule("jar",
		blueprint.RuleParams{
			Command:     `${config.SoongZipCmd} -jar -o $out $jarArgs`,
			Command:        `${config.SoongZipCmd} -jar -o $out @$out.rsp`,
			CommandDeps:    []string{"${config.SoongZipCmd}"},
			Rspfile:        "$out.rsp",
			RspfileContent: "$jarArgs",
		},
		"jarArgs")

+3 −0
Original line number Diff line number Diff line
@@ -26,5 +26,8 @@ bootstrap_go_package {
        "zip.go",
        "rate_limit.go",
    ],
    testSrcs: [
      "zip_test.go",
    ],
}
+37 −20
Original line number Diff line number Diff line
@@ -120,30 +120,12 @@ func (d *dir) Set(s string) error {
}

var (
	out            = flag.String("o", "", "file to write zip file to")
	manifest       = flag.String("m", "", "input jar manifest file name")
	directories    = flag.Bool("d", false, "include directories in zip")
	rootPrefix     = flag.String("P", "", "path prefix within the zip at which to place files")
	relativeRoot   = flag.String("C", "", "path to use as relative root of files in following -f, -l, or -D arguments")
	parallelJobs   = flag.Int("j", runtime.NumCPU(), "number of parallel threads to use")
	compLevel      = flag.Int("L", 5, "deflate compression level (0-9)")
	emulateJar     = flag.Bool("jar", false, "modify the resultant .zip to emulate the output of 'jar'")
	writeIfChanged = flag.Bool("write_if_changed", false, "only update resultant .zip if it has changed")
	rootPrefix, relativeRoot *string

	fArgs            zip.FileArgs
	nonDeflatedFiles = make(uniqueSet)

	cpuProfile = flag.String("cpuprofile", "", "write cpu profile to file")
	traceFile  = flag.String("trace", "", "write trace to file")
)

func init() {
	flag.Var(&listFiles{}, "l", "file containing list of .class files")
	flag.Var(&dir{}, "D", "directory to include in zip")
	flag.Var(&file{}, "f", "file to include in zip")
	flag.Var(&nonDeflatedFiles, "s", "file path to be stored within the zip without compression")
}

func usage() {
	fmt.Fprintf(os.Stderr, "usage: zip -o zipfile [-m manifest] -C dir [-f|-l file]...\n")
	flag.PrintDefaults()
@@ -151,7 +133,42 @@ func usage() {
}

func main() {
	flag.Parse()
	var expandedArgs []string
	for _, arg := range os.Args {
		if strings.HasPrefix(arg, "@") {
			bytes, err := ioutil.ReadFile(strings.TrimPrefix(arg, "@"))
			if err != nil {
				fmt.Fprintln(os.Stderr, err.Error())
				os.Exit(1)
			}
			respArgs := zip.ReadRespFile(bytes)
			expandedArgs = append(expandedArgs, respArgs...)
		} else {
			expandedArgs = append(expandedArgs, arg)
		}
	}

	flags := flag.NewFlagSet("flags", flag.ExitOnError)

	out := flags.String("o", "", "file to write zip file to")
	manifest := flags.String("m", "", "input jar manifest file name")
	directories := flags.Bool("d", false, "include directories in zip")
	rootPrefix = flags.String("P", "", "path prefix within the zip at which to place files")
	relativeRoot = flags.String("C", "", "path to use as relative root of files in following -f, -l, or -D arguments")
	parallelJobs := flags.Int("j", runtime.NumCPU(), "number of parallel threads to use")
	compLevel := flags.Int("L", 5, "deflate compression level (0-9)")
	emulateJar := flags.Bool("jar", false, "modify the resultant .zip to emulate the output of 'jar'")
	writeIfChanged := flags.Bool("write_if_changed", false, "only update resultant .zip if it has changed")

	cpuProfile := flags.String("cpuprofile", "", "write cpu profile to file")
	traceFile := flags.String("trace", "", "write trace to file")

	flags.Var(&listFiles{}, "l", "file containing list of .class files")
	flags.Var(&dir{}, "D", "directory to include in zip")
	flags.Var(&file{}, "f", "file to include in zip")
	flags.Var(&nonDeflatedFiles, "s", "file path to be stored within the zip without compression")

	flags.Parse(expandedArgs[1:])

	err := zip.Run(zip.ZipArgs{
		FileArgs:                 fArgs,
+44 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import (
	"strings"
	"sync"
	"time"
	"unicode"

	"github.com/google/blueprint/pathtools"

@@ -132,6 +133,49 @@ type ZipArgs struct {
	WriteIfChanged           bool
}

const NOQUOTE = '\x00'

func ReadRespFile(bytes []byte) []string {
	var args []string
	var arg []rune

	isEscaping := false
	quotingStart := NOQUOTE
	for _, c := range string(bytes) {
		switch {
		case isEscaping:
			if quotingStart == '"' {
				if !(c == '"' || c == '\\') {
					// '\"' or '\\' will be escaped under double quoting.
					arg = append(arg, '\\')
				}
			}
			arg = append(arg, c)
			isEscaping = false
		case c == '\\' && quotingStart != '\'':
			isEscaping = true
		case quotingStart == NOQUOTE && (c == '\'' || c == '"'):
			quotingStart = c
		case quotingStart != NOQUOTE && c == quotingStart:
			quotingStart = NOQUOTE
		case quotingStart == NOQUOTE && unicode.IsSpace(c):
			// Current character is a space outside quotes
			if len(arg) != 0 {
				args = append(args, string(arg))
			}
			arg = arg[:0]
		default:
			arg = append(arg, c)
		}
	}

	if len(arg) != 0 {
		args = append(args, string(arg))
	}

	return args
}

func Run(args ZipArgs) (err error) {
	if args.CpuProfileFilePath != "" {
		f, err := os.Create(args.CpuProfileFilePath)

zip/zip_test.go

0 → 100644
+87 −0
Original line number Diff line number Diff line
// Copyright 2018 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package zip

import (
	"reflect"
	"testing"
)

func TestReadRespFile(t *testing.T) {
	testCases := []struct {
		name, in string
		out      []string
	}{
		{
			name: "single quoting test case 1",
			in:   `./cmd '"'-C`,
			out:  []string{"./cmd", `"-C`},
		},
		{
			name: "single quoting test case 2",
			in:   `./cmd '-C`,
			out:  []string{"./cmd", `-C`},
		},
		{
			name: "single quoting test case 3",
			in:   `./cmd '\"'-C`,
			out:  []string{"./cmd", `\"-C`},
		},
		{
			name: "single quoting test case 4",
			in:   `./cmd '\\'-C`,
			out:  []string{"./cmd", `\\-C`},
		},
		{
			name: "none quoting test case 1",
			in:   `./cmd \'-C`,
			out:  []string{"./cmd", `'-C`},
		},
		{
			name: "none quoting test case 2",
			in:   `./cmd \\-C`,
			out:  []string{"./cmd", `\-C`},
		},
		{
			name: "none quoting test case 3",
			in:   `./cmd \"-C`,
			out:  []string{"./cmd", `"-C`},
		},
		{
			name: "double quoting test case 1",
			in:   `./cmd "'"-C`,
			out:  []string{"./cmd", `'-C`},
		},
		{
			name: "double quoting test case 2",
			in:   `./cmd "\\"-C`,
			out:  []string{"./cmd", `\-C`},
		},
		{
			name: "double quoting test case 3",
			in:   `./cmd "\""-C`,
			out:  []string{"./cmd", `"-C`},
		},
	}

	for _, testCase := range testCases {
		t.Run(testCase.name, func(t *testing.T) {
			got := ReadRespFile([]byte(testCase.in))
			if !reflect.DeepEqual(got, testCase.out) {
				t.Errorf("expected %q got %q", testCase.out, got)
			}
		})
	}
}