blob: d4c3431e90ce2b7c5136c853ff9fdd5b3c04649e [file] [log] [blame] [edit]
// Copyright 2017 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 build
import (
"compress/gzip"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
func absPath(ctx Context, p string) string {
ret, err := filepath.Abs(p)
if err != nil {
ctx.Fatalf("Failed to get absolute path: %v", err)
}
return ret
}
// indexList finds the index of a string in a []string
func indexList(s string, list []string) int {
for i, l := range list {
if l == s {
return i
}
}
return -1
}
// inList determines whether a string is in a []string
func inList(s string, list []string) bool {
return indexList(s, list) != -1
}
// removeFromlist removes all occurrences of the string in list.
func removeFromList(s string, list []string) []string {
filteredList := make([]string, 0, len(list))
for _, ls := range list {
if s != ls {
filteredList = append(filteredList, ls)
}
}
return filteredList
}
// ensureDirectoriesExist is a shortcut to os.MkdirAll, sending errors to the ctx logger.
func ensureDirectoriesExist(ctx Context, dirs ...string) {
for _, dir := range dirs {
err := os.MkdirAll(dir, 0777)
if err != nil {
ctx.Fatalf("Error creating %s: %q\n", dir, err)
}
}
}
// ensureEmptyDirectoriesExist ensures that the given directories exist and are empty
func ensureEmptyDirectoriesExist(ctx Context, dirs ...string) {
// remove all the directories
for _, dir := range dirs {
seenErr := map[string]bool{}
for {
err := os.RemoveAll(dir)
if err == nil {
break
}
if pathErr, ok := err.(*os.PathError); !ok ||
dir == pathErr.Path || seenErr[pathErr.Path] {
ctx.Fatalf("Error removing %s: %q\n", dir, err)
} else {
seenErr[pathErr.Path] = true
err = os.Chmod(filepath.Dir(pathErr.Path), 0700)
if err != nil {
ctx.Fatal(err)
}
}
}
}
// recreate all the directories
ensureDirectoriesExist(ctx, dirs...)
}
// ensureEmptyFileExists ensures that the containing directory exists, and the
// specified file exists. If it doesn't exist, it will write an empty file.
func ensureEmptyFileExists(ctx Context, file string) {
ensureDirectoriesExist(ctx, filepath.Dir(file))
if _, err := os.Stat(file); os.IsNotExist(err) {
f, err := os.Create(file)
if err != nil {
ctx.Fatalf("Error creating %s: %q\n", file, err)
}
f.Close()
} else if err != nil {
ctx.Fatalf("Error checking %s: %q\n", file, err)
}
}
// singleUnquote is similar to strconv.Unquote, but can handle multi-character strings inside single quotes.
func singleUnquote(str string) (string, bool) {
if len(str) < 2 || str[0] != '\'' || str[len(str)-1] != '\'' {
return "", false
}
return str[1 : len(str)-1], true
}
// decodeKeyValue decodes a key=value string
func decodeKeyValue(str string) (string, string, bool) {
idx := strings.IndexRune(str, '=')
if idx == -1 {
return "", "", false
}
return str[:idx], str[idx+1:], true
}
// copyFile copies a file from src to dst. filepath.Dir(dst) must exist.
func copyFile(src, dst string) (int64, error) {
source, err := os.Open(src)
if err != nil {
return 0, err
}
defer source.Close()
destination, err := os.Create(dst)
if err != nil {
return 0, err
}
defer destination.Close()
return io.Copy(destination, source)
}
// gzipFileToDir writes a compressed copy of src to destDir with the suffix ".gz".
func gzipFileToDir(src, destDir string) error {
in, err := os.Open(src)
if err != nil {
return fmt.Errorf("failed to open %s: %s", src, err.Error())
}
defer in.Close()
dest := filepath.Join(destDir, filepath.Base(src)+".gz")
out, err := os.OpenFile(dest, os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
return fmt.Errorf("failed to open %s: %s", dest, err.Error())
}
defer out.Close()
gz := gzip.NewWriter(out)
defer gz.Close()
_, err = io.Copy(gz, in)
if err != nil {
return fmt.Errorf("failed to gzip %s: %s", dest, err.Error())
}
return nil
}