blob: 764ed0ddfddaf8c05c02bd1ec75b9da90a0f0c4b [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysed688482015-06-03 12:21:27 +00002//
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.
14package com.google.devtools.build.lib.vfs;
15
16import com.google.common.base.Splitter;
17
18import java.io.IOException;
19import java.util.ArrayList;
20import java.util.List;
21
22import javax.annotation.Nullable;
23
24/**
25 * Parse and search $PATH, the binary search path for executables.
26 */
27public class SearchPath {
28 private static final Splitter SEPARATOR = Splitter.on(':');
29
30 /**
31 * Parses a $PATH value into a list of paths. A Null search path is treated as an empty one.
Han-Wen Nienhuys24645262015-06-03 13:50:05 +000032 * Relative entries in $PATH are ignored.
Han-Wen Nienhuysed688482015-06-03 12:21:27 +000033 */
34 public static List<Path> parse(FileSystem fs, @Nullable String searchPath) {
35 List<Path> paths = new ArrayList<>();
36 if (searchPath == null) {
37 return paths;
38 }
39 for (String p : SEPARATOR.split(searchPath)) {
nharmatab4060b62017-04-04 17:11:39 +000040 PathFragment pf = PathFragment.create(p);
Han-Wen Nienhuys24645262015-06-03 13:50:05 +000041
42 if (pf.isAbsolute()) {
43 paths.add(fs.getPath(pf));
44 }
Han-Wen Nienhuysed688482015-06-03 12:21:27 +000045 }
46 return paths;
47 }
48
49 /**
50 * Finds the first executable called {@code exe} in the searchPath.
51 * If {@code exe} is not a basename, it will always return null. This should be equivalent to
52 * running which(1).
53 */
54 @Nullable
55 public static Path which(List<Path> searchPath, String exe) {
nharmatab4060b62017-04-04 17:11:39 +000056 PathFragment fragment = PathFragment.create(exe);
Han-Wen Nienhuysed688482015-06-03 12:21:27 +000057 if (fragment.segmentCount() != 1 || fragment.isAbsolute()) {
58 return null;
59 }
60
61 for (Path p : searchPath) {
62 Path ch = p.getChild(exe);
63
64 try {
65 if (ch.exists() && ch.isExecutable()) {
66 return ch;
67 }
68 } catch (IOException e) {
69 // Like which(1), we ignore any IO exception (disk on fire, permission denied etc.)
70 }
71 }
72 return null;
73 }
74}