Merge "WriteFileRule: Chunk long content and merge them to result"

This commit is contained in:
Treehugger Robot 2020-12-03 04:44:02 +00:00 committed by Gerrit Code Review
commit c0a7b832f3
3 changed files with 55 additions and 4 deletions

View file

@ -15,6 +15,7 @@
package android
import (
"fmt"
"strings"
"testing"
@ -97,7 +98,7 @@ var (
// content to file.
writeFile = pctx.AndroidStaticRule("writeFile",
blueprint.RuleParams{
Command: `/bin/bash -c 'echo -e "$$0" > $out' $content`,
Command: `/bin/bash -c 'echo -e -n "$$0" > $out' $content`,
Description: "writing file $out",
},
"content")
@ -133,9 +134,7 @@ var (
shellUnescaper = strings.NewReplacer(`'\''`, `'`)
)
// WriteFileRule creates a ninja rule to write contents to a file. The contents will be escaped
// so that the file contains exactly the contents passed to the function, plus a trailing newline.
func WriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) {
func buildWriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) {
content = echoEscaper.Replace(content)
content = proptools.ShellEscape(content)
if content == "" {
@ -151,6 +150,31 @@ func WriteFileRule(ctx BuilderContext, outputFile WritablePath, content string)
})
}
// WriteFileRule creates a ninja rule to write contents to a file. The contents will be escaped
// so that the file contains exactly the contents passed to the function, plus a trailing newline.
func WriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) {
// This is MAX_ARG_STRLEN subtracted with some safety to account for shell escapes
const SHARD_SIZE = 131072 - 10000
content += "\n"
if len(content) > SHARD_SIZE {
var chunks WritablePaths
for i, c := range ShardString(content, SHARD_SIZE) {
tempPath := outputFile.ReplaceExtension(ctx, fmt.Sprintf("%s.%d", outputFile.Ext(), i))
buildWriteFileRule(ctx, tempPath, c)
chunks = append(chunks, tempPath)
}
ctx.Build(pctx, BuildParams{
Rule: Cat,
Inputs: chunks.Paths(),
Output: outputFile,
Description: "Merging to " + outputFile.Base(),
})
return
}
buildWriteFileRule(ctx, outputFile, content)
}
// shellUnescape reverses proptools.ShellEscape
func shellUnescape(s string) string {
// Remove leading and trailing quotes if present

View file

@ -138,6 +138,8 @@ type WritablePath interface {
// the writablePath method doesn't directly do anything,
// but it allows a struct to distinguish between whether or not it implements the WritablePath interface
writablePath()
ReplaceExtension(ctx PathContext, ext string) OutputPath
}
type genPathProvider interface {
@ -1249,6 +1251,10 @@ func (p InstallPath) buildDir() string {
return p.config.buildDir
}
func (p InstallPath) ReplaceExtension(ctx PathContext, ext string) OutputPath {
panic("Not implemented")
}
var _ Path = InstallPath{}
var _ WritablePath = InstallPath{}
@ -1511,6 +1517,10 @@ func (p PhonyPath) buildDir() string {
return p.config.buildDir
}
func (p PhonyPath) ReplaceExtension(ctx PathContext, ext string) OutputPath {
panic("Not implemented")
}
var _ Path = PhonyPath{}
var _ WritablePath = PhonyPath{}

View file

@ -401,6 +401,23 @@ func ShardPaths(paths Paths, shardSize int) []Paths {
return ret
}
// ShardString takes a string and returns a slice of strings where the length of each one is
// at most shardSize.
func ShardString(s string, shardSize int) []string {
if len(s) == 0 {
return nil
}
ret := make([]string, 0, (len(s)+shardSize-1)/shardSize)
for len(s) > shardSize {
ret = append(ret, s[0:shardSize])
s = s[shardSize:]
}
if len(s) > 0 {
ret = append(ret, s)
}
return ret
}
// ShardStrings takes a slice of strings, and returns a slice of slices of strings where each one has at most shardSize
// elements.
func ShardStrings(s []string, shardSize int) [][]string {