1*9e965d6fSRomain Jobredeaux# Copyright 2018 The Bazel Authors. All rights reserved. 2*9e965d6fSRomain Jobredeaux# 3*9e965d6fSRomain Jobredeaux# Licensed under the Apache License, Version 2.0 (the "License"); 4*9e965d6fSRomain Jobredeaux# you may not use this file except in compliance with the License. 5*9e965d6fSRomain Jobredeaux# You may obtain a copy of the License at 6*9e965d6fSRomain Jobredeaux# 7*9e965d6fSRomain Jobredeaux# http://www.apache.org/licenses/LICENSE-2.0 8*9e965d6fSRomain Jobredeaux# 9*9e965d6fSRomain Jobredeaux# Unless required by applicable law or agreed to in writing, software 10*9e965d6fSRomain Jobredeaux# distributed under the License is distributed on an "AS IS" BASIS, 11*9e965d6fSRomain Jobredeaux# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9e965d6fSRomain Jobredeaux# See the License for the specific language governing permissions and 13*9e965d6fSRomain Jobredeaux# limitations under the License. 14*9e965d6fSRomain Jobredeaux 15*9e965d6fSRomain Jobredeaux"""Bazel Path APIs for the Android rules.""" 16*9e965d6fSRomain Jobredeaux 17*9e965d6fSRomain Jobredeaux# TODO(djwhang): Get the path separator in a platform agnostic manner. 18*9e965d6fSRomain Jobredeaux_PATH_SEP = "/" 19*9e965d6fSRomain Jobredeaux_TEST_SRCDIR = "${TEST_SRCDIR}" 20*9e965d6fSRomain Jobredeaux 21*9e965d6fSRomain Jobredeauxdef _is_absolute(path): 22*9e965d6fSRomain Jobredeaux # TODO(djwhang): This is not cross platform safe. Windows absolute paths 23*9e965d6fSRomain Jobredeaux # do not start with "//", rather "C:\". 24*9e965d6fSRomain Jobredeaux return path.startswith(_PATH_SEP) 25*9e965d6fSRomain Jobredeaux 26*9e965d6fSRomain Jobredeauxdef _split(path): 27*9e965d6fSRomain Jobredeaux return path.split(_PATH_SEP) 28*9e965d6fSRomain Jobredeaux 29*9e965d6fSRomain Jobredeauxdef _join(path_segments): 30*9e965d6fSRomain Jobredeaux return _PATH_SEP.join(path_segments) 31*9e965d6fSRomain Jobredeaux 32*9e965d6fSRomain Jobredeauxdef _normalize_path(path, posix = False): 33*9e965d6fSRomain Jobredeaux return _PATH_SEP.join( 34*9e965d6fSRomain Jobredeaux _normalize_path_fragments( 35*9e965d6fSRomain Jobredeaux path.split(_PATH_SEP), 36*9e965d6fSRomain Jobredeaux posix = posix, 37*9e965d6fSRomain Jobredeaux ), 38*9e965d6fSRomain Jobredeaux ) 39*9e965d6fSRomain Jobredeaux 40*9e965d6fSRomain Jobredeauxdef _normalize_path_fragments(path_fragments, posix = False): 41*9e965d6fSRomain Jobredeaux normalized_path_fragments = [] 42*9e965d6fSRomain Jobredeaux for idx, fragment in enumerate(path_fragments): 43*9e965d6fSRomain Jobredeaux if not fragment and idx > 0: 44*9e965d6fSRomain Jobredeaux continue 45*9e965d6fSRomain Jobredeaux if fragment == ".": 46*9e965d6fSRomain Jobredeaux continue 47*9e965d6fSRomain Jobredeaux if fragment == ".." and not posix: 48*9e965d6fSRomain Jobredeaux if normalized_path_fragments: 49*9e965d6fSRomain Jobredeaux last = normalized_path_fragments.pop() 50*9e965d6fSRomain Jobredeaux if last == ".." or last == "": 51*9e965d6fSRomain Jobredeaux normalized_path_fragments.append(last) 52*9e965d6fSRomain Jobredeaux else: 53*9e965d6fSRomain Jobredeaux continue 54*9e965d6fSRomain Jobredeaux normalized_path_fragments.append(fragment) 55*9e965d6fSRomain Jobredeaux if len(normalized_path_fragments) == 1 and not normalized_path_fragments[0]: 56*9e965d6fSRomain Jobredeaux normalized_path_fragments.append("") 57*9e965d6fSRomain Jobredeaux return normalized_path_fragments 58*9e965d6fSRomain Jobredeaux 59*9e965d6fSRomain Jobredeauxdef _relative_path(path1, path2): 60*9e965d6fSRomain Jobredeaux if not path1 or _is_absolute(path2): 61*9e965d6fSRomain Jobredeaux return path2 62*9e965d6fSRomain Jobredeaux 63*9e965d6fSRomain Jobredeaux path1_fragments = _normalize_path_fragments(_split(path1)) 64*9e965d6fSRomain Jobredeaux path2_fragments = _normalize_path_fragments(_split(path2)) 65*9e965d6fSRomain Jobredeaux path1_idx = len(path1_fragments) # index move backwards 66*9e965d6fSRomain Jobredeaux path2_idx = -1 67*9e965d6fSRomain Jobredeaux for idx, fragment in enumerate(path2_fragments): 68*9e965d6fSRomain Jobredeaux if fragment == "..": 69*9e965d6fSRomain Jobredeaux path1_idx -= 1 70*9e965d6fSRomain Jobredeaux else: 71*9e965d6fSRomain Jobredeaux path2_idx = idx 72*9e965d6fSRomain Jobredeaux break 73*9e965d6fSRomain Jobredeaux 74*9e965d6fSRomain Jobredeaux relative_path_fragments = [] 75*9e965d6fSRomain Jobredeaux if path1_idx >= 0: 76*9e965d6fSRomain Jobredeaux relative_path_fragments.extend(path1_fragments[:path1_idx]) 77*9e965d6fSRomain Jobredeaux if path2_idx >= 0: 78*9e965d6fSRomain Jobredeaux relative_path_fragments.extend(path2_fragments[path2_idx:]) 79*9e965d6fSRomain Jobredeaux return _join(_normalize_path_fragments(relative_path_fragments)) 80*9e965d6fSRomain Jobredeaux 81*9e965d6fSRomain Jobredeauxdef _make_test_srcdir_path(ctx, *path_fragments): 82*9e965d6fSRomain Jobredeaux """Creates a filepath relative to TEST_SRCDIR. 83*9e965d6fSRomain Jobredeaux 84*9e965d6fSRomain Jobredeaux Args: 85*9e965d6fSRomain Jobredeaux ctx: Starlark context. 86*9e965d6fSRomain Jobredeaux *path_fragments: Directories/file to join into a single path. 87*9e965d6fSRomain Jobredeaux Returns: 88*9e965d6fSRomain Jobredeaux A filepath that's spearated by the host's filepath separator. 89*9e965d6fSRomain Jobredeaux """ 90*9e965d6fSRomain Jobredeaux fragments = [_TEST_SRCDIR, ctx.workspace_name] 91*9e965d6fSRomain Jobredeaux for path_fragment in path_fragments: 92*9e965d6fSRomain Jobredeaux fragments += _normalize_path_fragments(_split(path_fragment)) 93*9e965d6fSRomain Jobredeaux return _join(fragments) 94*9e965d6fSRomain Jobredeaux 95*9e965d6fSRomain Jobredeauxpath = struct( 96*9e965d6fSRomain Jobredeaux is_absolute = _is_absolute, 97*9e965d6fSRomain Jobredeaux join = _join, 98*9e965d6fSRomain Jobredeaux normalize = _normalize_path, 99*9e965d6fSRomain Jobredeaux relative = _relative_path, 100*9e965d6fSRomain Jobredeaux split = _split, 101*9e965d6fSRomain Jobredeaux make_test_srcdir_path = _make_test_srcdir_path, 102*9e965d6fSRomain Jobredeaux) 103