• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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