blob: d44cd6daf39bd5e80acfa716ad69326649a4f5b6 [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 (
Patrice Arruda7cc20742020-06-10 18:48:01 +000018 "io"
Dan Willemsen1e704462016-08-21 15:17:17 -070019 "os"
20 "path/filepath"
21 "strings"
22)
23
Dan Willemsend9e8f0a2017-10-30 13:42:06 -070024func absPath(ctx Context, p string) string {
25 ret, err := filepath.Abs(p)
26 if err != nil {
27 ctx.Fatalf("Failed to get absolute path: %v", err)
28 }
29 return ret
30}
31
Dan Willemsen1e704462016-08-21 15:17:17 -070032// indexList finds the index of a string in a []string
33func indexList(s string, list []string) int {
34 for i, l := range list {
35 if l == s {
36 return i
37 }
38 }
39
40 return -1
41}
42
43// inList determines whether a string is in a []string
44func inList(s string, list []string) bool {
45 return indexList(s, list) != -1
46}
47
Patrice Arruda13848222019-04-22 17:12:02 -070048// removeFromlist removes all occurrences of the string in list.
49func removeFromList(s string, list []string) []string {
50 filteredList := make([]string, 0, len(list))
51 for _, ls := range list {
52 if s != ls {
53 filteredList = append(filteredList, ls)
54 }
55 }
56 return filteredList
57}
58
Dan Willemsen1e704462016-08-21 15:17:17 -070059// ensureDirectoriesExist is a shortcut to os.MkdirAll, sending errors to the ctx logger.
60func ensureDirectoriesExist(ctx Context, dirs ...string) {
61 for _, dir := range dirs {
62 err := os.MkdirAll(dir, 0777)
63 if err != nil {
64 ctx.Fatalf("Error creating %s: %q\n", dir, err)
65 }
66 }
67}
68
Jeff Gastonefc1b412017-03-29 17:29:06 -070069// ensureEmptyDirectoriesExist ensures that the given directories exist and are empty
70func ensureEmptyDirectoriesExist(ctx Context, dirs ...string) {
71 // remove all the directories
72 for _, dir := range dirs {
Dan Willemsenfe8b6452018-05-12 18:34:24 -070073 seenErr := map[string]bool{}
74 for {
75 err := os.RemoveAll(dir)
76 if err == nil {
77 break
78 }
79
80 if pathErr, ok := err.(*os.PathError); !ok ||
81 dir == pathErr.Path || seenErr[pathErr.Path] {
82
83 ctx.Fatalf("Error removing %s: %q\n", dir, err)
84 } else {
85 seenErr[pathErr.Path] = true
86 err = os.Chmod(filepath.Dir(pathErr.Path), 0700)
87 if err != nil {
88 ctx.Fatal(err)
89 }
90 }
Jeff Gastonefc1b412017-03-29 17:29:06 -070091 }
92 }
93 // recreate all the directories
94 ensureDirectoriesExist(ctx, dirs...)
95}
96
Dan Willemsen1e704462016-08-21 15:17:17 -070097// ensureEmptyFileExists ensures that the containing directory exists, and the
98// specified file exists. If it doesn't exist, it will write an empty file.
99func ensureEmptyFileExists(ctx Context, file string) {
100 ensureDirectoriesExist(ctx, filepath.Dir(file))
101 if _, err := os.Stat(file); os.IsNotExist(err) {
102 f, err := os.Create(file)
103 if err != nil {
104 ctx.Fatalf("Error creating %s: %q\n", file, err)
105 }
106 f.Close()
107 } else if err != nil {
108 ctx.Fatalf("Error checking %s: %q\n", file, err)
109 }
110}
111
112// singleUnquote is similar to strconv.Unquote, but can handle multi-character strings inside single quotes.
113func singleUnquote(str string) (string, bool) {
114 if len(str) < 2 || str[0] != '\'' || str[len(str)-1] != '\'' {
115 return "", false
116 }
117 return str[1 : len(str)-1], true
118}
119
120// decodeKeyValue decodes a key=value string
121func decodeKeyValue(str string) (string, string, bool) {
122 idx := strings.IndexRune(str, '=')
123 if idx == -1 {
124 return "", "", false
125 }
126 return str[:idx], str[idx+1:], true
127}
Patrice Arruda7cc20742020-06-10 18:48:01 +0000128
129// copyFile copies a file from src to dst. filepath.Dir(dst) must exist.
130func copyFile(src, dst string) (int64, error) {
131 source, err := os.Open(src)
132 if err != nil {
133 return 0, err
134 }
135 defer source.Close()
136
137 destination, err := os.Create(dst)
138 if err != nil {
139 return 0, err
140 }
141 defer destination.Close()
142
143 return io.Copy(destination, source)
144}