blob: 75e6753b7874b978e293acc6d5990ce5a021eb99 [file] [log] [blame]
Dan Willemsen1e704462016-08-21 15:17:17 -07001// 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
Dan Willemsend9e8f0a2017-10-30 13:42:06 -070023func 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
Dan Willemsen1e704462016-08-21 15:17:17 -070031// 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
Patrice Arruda13848222019-04-22 17:12:02 -070047// removeFromlist removes all occurrences of the string in list.
48func removeFromList(s string, list []string) []string {
49 filteredList := make([]string, 0, len(list))
50 for _, ls := range list {
51 if s != ls {
52 filteredList = append(filteredList, ls)
53 }
54 }
55 return filteredList
56}
57
Dan Willemsen1e704462016-08-21 15:17:17 -070058// ensureDirectoriesExist is a shortcut to os.MkdirAll, sending errors to the ctx logger.
59func ensureDirectoriesExist(ctx Context, dirs ...string) {
60 for _, dir := range dirs {
61 err := os.MkdirAll(dir, 0777)
62 if err != nil {
63 ctx.Fatalf("Error creating %s: %q\n", dir, err)
64 }
65 }
66}
67
Jeff Gastonefc1b412017-03-29 17:29:06 -070068// ensureEmptyDirectoriesExist ensures that the given directories exist and are empty
69func ensureEmptyDirectoriesExist(ctx Context, dirs ...string) {
70 // remove all the directories
71 for _, dir := range dirs {
Dan Willemsenfe8b6452018-05-12 18:34:24 -070072 seenErr := map[string]bool{}
73 for {
74 err := os.RemoveAll(dir)
75 if err == nil {
76 break
77 }
78
79 if pathErr, ok := err.(*os.PathError); !ok ||
80 dir == pathErr.Path || seenErr[pathErr.Path] {
81
82 ctx.Fatalf("Error removing %s: %q\n", dir, err)
83 } else {
84 seenErr[pathErr.Path] = true
85 err = os.Chmod(filepath.Dir(pathErr.Path), 0700)
86 if err != nil {
87 ctx.Fatal(err)
88 }
89 }
Jeff Gastonefc1b412017-03-29 17:29:06 -070090 }
91 }
92 // recreate all the directories
93 ensureDirectoriesExist(ctx, dirs...)
94}
95
Dan Willemsen1e704462016-08-21 15:17:17 -070096// ensureEmptyFileExists ensures that the containing directory exists, and the
97// specified file exists. If it doesn't exist, it will write an empty file.
98func ensureEmptyFileExists(ctx Context, file string) {
99 ensureDirectoriesExist(ctx, filepath.Dir(file))
100 if _, err := os.Stat(file); os.IsNotExist(err) {
101 f, err := os.Create(file)
102 if err != nil {
103 ctx.Fatalf("Error creating %s: %q\n", file, err)
104 }
105 f.Close()
106 } else if err != nil {
107 ctx.Fatalf("Error checking %s: %q\n", file, err)
108 }
109}
110
111// singleUnquote is similar to strconv.Unquote, but can handle multi-character strings inside single quotes.
112func singleUnquote(str string) (string, bool) {
113 if len(str) < 2 || str[0] != '\'' || str[len(str)-1] != '\'' {
114 return "", false
115 }
116 return str[1 : len(str)-1], true
117}
118
119// decodeKeyValue decodes a key=value string
120func decodeKeyValue(str string) (string, string, bool) {
121 idx := strings.IndexRune(str, '=')
122 if idx == -1 {
123 return "", "", false
124 }
125 return str[:idx], str[idx+1:], true
126}