1// Copyright 2017 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 build 16 17import ( 18 "os" 19 "path/filepath" 20 "strings" 21) 22 23func absPath(ctx Context, p string) string { 24 ret, err := filepath.Abs(p) 25 if err != nil { 26 ctx.Fatalf("Failed to get absolute path: %v", err) 27 } 28 return ret 29} 30 31// indexList finds the index of a string in a []string 32func indexList(s string, list []string) int { 33 for i, l := range list { 34 if l == s { 35 return i 36 } 37 } 38 39 return -1 40} 41 42// inList determines whether a string is in a []string 43func inList(s string, list []string) bool { 44 return indexList(s, list) != -1 45} 46 47// ensureDirectoriesExist is a shortcut to os.MkdirAll, sending errors to the ctx logger. 48func ensureDirectoriesExist(ctx Context, dirs ...string) { 49 for _, dir := range dirs { 50 err := os.MkdirAll(dir, 0777) 51 if err != nil { 52 ctx.Fatalf("Error creating %s: %q\n", dir, err) 53 } 54 } 55} 56 57// ensureEmptyDirectoriesExist ensures that the given directories exist and are empty 58func ensureEmptyDirectoriesExist(ctx Context, dirs ...string) { 59 // remove all the directories 60 for _, dir := range dirs { 61 seenErr := map[string]bool{} 62 for { 63 err := os.RemoveAll(dir) 64 if err == nil { 65 break 66 } 67 68 if pathErr, ok := err.(*os.PathError); !ok || 69 dir == pathErr.Path || seenErr[pathErr.Path] { 70 71 ctx.Fatalf("Error removing %s: %q\n", dir, err) 72 } else { 73 seenErr[pathErr.Path] = true 74 err = os.Chmod(filepath.Dir(pathErr.Path), 0700) 75 if err != nil { 76 ctx.Fatal(err) 77 } 78 } 79 } 80 } 81 // recreate all the directories 82 ensureDirectoriesExist(ctx, dirs...) 83} 84 85// ensureEmptyFileExists ensures that the containing directory exists, and the 86// specified file exists. If it doesn't exist, it will write an empty file. 87func ensureEmptyFileExists(ctx Context, file string) { 88 ensureDirectoriesExist(ctx, filepath.Dir(file)) 89 if _, err := os.Stat(file); os.IsNotExist(err) { 90 f, err := os.Create(file) 91 if err != nil { 92 ctx.Fatalf("Error creating %s: %q\n", file, err) 93 } 94 f.Close() 95 } else if err != nil { 96 ctx.Fatalf("Error checking %s: %q\n", file, err) 97 } 98} 99 100// singleUnquote is similar to strconv.Unquote, but can handle multi-character strings inside single quotes. 101func singleUnquote(str string) (string, bool) { 102 if len(str) < 2 || str[0] != '\'' || str[len(str)-1] != '\'' { 103 return "", false 104 } 105 return str[1 : len(str)-1], true 106} 107 108// decodeKeyValue decodes a key=value string 109func decodeKeyValue(str string) (string, string, bool) { 110 idx := strings.IndexRune(str, '=') 111 if idx == -1 { 112 return "", "", false 113 } 114 return str[:idx], str[idx+1:], true 115} 116