-
Notifications
You must be signed in to change notification settings - Fork 57
/
bazel.go
160 lines (136 loc) · 4.46 KB
/
bazel.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright 2016 Google Inc.
//
// 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 bazel provides utilities for interacting with the surrounding Bazel environment.
package bazel
import (
"bufio"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/bazelbuild/rules_webtesting/go/cmdhelper"
)
// DefaultWorkspace is the name of the default Bazel workspace.
var DefaultWorkspace = "io_bazel_rules_webtesting"
// Runfile returns an absolute path to the specified file in the runfiles directory of the running target.
// It searches the current working directory, RunfilesPath() directory, and RunfilesPath()/TestWorkspace().
// Returns an error if unable to locate RunfilesPath() or if the file does not exist.
func Runfile(path string) (string, error) {
if _, err := os.Stat(path); err == nil {
// absolute path or found in current working directory
return path, nil
}
if cmdhelper.IsTruthyEnv("RUNFILES_MANIFEST_ONLY") {
filename, err := runfileInManifest(path)
if err != nil {
return "", fmt.Errorf("RUNFILES_MANIFEST_ONLY is set but unable to locate %q in RUNFILES_MANIFEST_FILE: %v", path, err)
}
return filename, nil
}
runfiles, err := RunfilesPath()
if err != nil {
return "", fmt.Errorf("Unable to locate TEST_SRCDIR while looking for %q: %v", path, err)
}
filename := filepath.Join(runfiles, path)
if _, err := os.Stat(filename); err == nil {
// found at RunfilesPath()/path
return filename, nil
}
filename = filepath.Join(runfiles, TestWorkspace(), path)
if _, err := os.Stat(filename); err == nil {
// found at RunfilesPath()/TestWorkspace()/path
return filename, nil
}
filename, err = runfileInManifest(path)
if err != nil {
return "", fmt.Errorf("Unable to locate %q in TEST_SRCDIR or RUNFILES_MANIFEST_FILE", path)
}
return filename, nil
}
// RunfilesPath return the path to the run files tree for this test.
// It returns an error if TEST_SRCDIR does not exist.
func RunfilesPath() (string, error) {
const srcEnv = "TEST_SRCDIR"
if src, ok := os.LookupEnv(srcEnv); ok {
return src, nil
}
return "", fmt.Errorf("environment variable %q is not defined, are you running with bazel test", srcEnv)
}
// NewTmpDir creates a new temporary directory in TestTmpDir().
func NewTmpDir(prefix string) (string, error) {
return ioutil.TempDir(TestTmpDir(), prefix)
}
// TestTmpDir returns the path the Bazel test temp directory.
// If TEST_TMPDIR is not defined, it returns the OS default temp dir.
func TestTmpDir() string {
if tmp, ok := os.LookupEnv("TEST_TMPDIR"); ok {
return tmp
}
return os.TempDir()
}
// TestWorkspace returns the name of the Bazel workspace for this test.
// If TEST_WORKSPACE is not defined, it returns DefaultWorkspace.
func TestWorkspace() string {
if ws, ok := os.LookupEnv("TEST_WORKSPACE"); ok {
return ws
}
return DefaultWorkspace
}
// RunfilesManifest returns the runfiles MANIFEST file.
func RunfilesManifest() (string, error) {
mp, ok := os.LookupEnv("RUNFILES_MANIFEST_FILE")
if !ok {
return "", errors.New("environment variable RUNFILES_MANIFEST_FILE is not defined, are you running with bazel test")
}
_, err := os.Stat(mp)
return mp, err
}
func runfileInManifest(path string) (string, error) {
// TODO(DrMarcII): Consider support for finding for TestWorkspace()/path in the manifest.
mp, err := RunfilesManifest()
if err != nil {
return "", err
}
f, err := os.Open(mp)
if err != nil {
return "", err
}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
tokens := strings.SplitN(scanner.Text(), " ", 2)
if len(tokens) != 2 {
continue
}
if tokens[0] == path {
if _, err := os.Stat(tokens[1]); err != nil {
continue
}
return tokens[1], nil
}
if strings.HasPrefix(path, tokens[0]) {
rel, err := filepath.Rel(tokens[0], path)
if err != nil {
continue
}
f := filepath.Join(tokens[1], rel)
if _, err := os.Stat(f); err != nil {
continue
}
return f, nil
}
}
return "", fmt.Errorf("cannot find runfile %q in manifest %q", path, mp)
}