diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/vfs/OsPathPolicy.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/vfs/OsPathPolicy.java | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/OsPathPolicy.java b/src/main/java/com/google/devtools/build/lib/vfs/OsPathPolicy.java new file mode 100644 index 0000000000..6b0380f8c8 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/vfs/OsPathPolicy.java @@ -0,0 +1,144 @@ +// Copyright 2017 The Bazel Authors. All rights reserved. +// +// 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 com.google.devtools.build.lib.vfs; + +import com.google.devtools.build.lib.util.OS; + +/** + * An interface class representing the differences in path style between different OSs. + * + * <p>Eg. case sensitivity, '/' mounts vs. 'C:/', etc. + */ +public interface OsPathPolicy { + int NORMALIZED = 0; // Path is normalized + int NEEDS_NORMALIZE = 1; // Path requires normalization + + /** Returns required normalization level, passed to {@link #normalize}. */ + int needsToNormalize(String path); + + /** + * Returns the required normalization level if an already normalized string is concatenated with + * another normalized path fragment. + * + * <p>This method may be faster than {@link #needsToNormalize(String)}. + */ + int needsToNormalizeSuffix(String normalizedSuffix); + + /** + * Normalizes the passed string according to the passed normalization level. + * + * @param normalizationLevel The normalizationLevel from {@link #needsToNormalize} + */ + String normalize(String path, int normalizationLevel); + + /** + * Returns the length of the mount, eg. 1 for unix '/', 3 for Windows 'C:/'. + * + * <p>If the path is relative, 0 is returned + */ + int getDriveStrLength(String path); + + /** Compares two path strings, using the given OS case sensitivity. */ + int compare(String s1, String s2); + + /** Compares two characters, using the given OS case sensitivity. */ + int compare(char c1, char c2); + + /** Tests two path strings for equality, using the given OS case sensitivity. */ + boolean equals(String s1, String s2); + + /** Computes the hash code for a path string. */ + int hash(String s); + + /** + * Returns whether the passed string starts with the given prefix, given the OS case sensitivity. + * + * <p>This is a pure string operation and doesn't need to worry about matching path segments. + */ + boolean startsWith(String path, String prefix); + + /** + * Returns whether the passed string ends with the given prefix, given the OS case sensitivity. + * + * <p>This is a pure string operation and doesn't need to worry about matching path segments. + */ + boolean endsWith(String path, String suffix); + + /** Returns the separator used for normalized paths. */ + char getSeparator(); + + /** Returns whether the unnormalized character c is a separator. */ + boolean isSeparator(char c); + + boolean isCaseSensitive(); + + static OsPathPolicy getFilePathOs() { + switch (OS.getCurrent()) { + case LINUX: + case FREEBSD: + case UNKNOWN: + return UnixOsPathPolicy.INSTANCE; + case DARWIN: + // NOTE: We *should* return a path policy that is case insensitive, + // but we currently don't handle this + return UnixOsPathPolicy.INSTANCE; + case WINDOWS: + return WindowsOsPathPolicy.INSTANCE; + default: + throw new AssertionError("Not covering all OSs"); + } + } + + /** Utilities for implementations of {@link OsPathPolicy}. */ + class Utils { + /** + * Normalizes any '.' and '..' in-place in the segment array by shifting other segments to the + * front. Returns the remaining number of items. + */ + static int removeRelativePaths(String[] segments, int starti, boolean isAbsolute) { + int segmentCount = 0; + int shift = starti; + int n = segments.length; + for (int i = starti; i < n; ++i) { + String segment = segments[i]; + switch (segment) { + case ".": + ++shift; + break; + case "..": + if (segmentCount > 0 && !segments[segmentCount - 1].equals("..")) { + // Remove the last segment, if there is one and it is not "..". This + // means that the resulting path can still contain ".." + // segments at the beginning. + segmentCount--; + shift += 2; + break; + } else if (isAbsolute) { + // If this is absolute, then just pop it the ".." off and remain at root + ++shift; + break; + } + // Fall through + default: + ++segmentCount; + if (shift > 0) { + segments[i - shift] = segments[i]; + } + break; + } + } + return segmentCount; + } + } +} |