blob: 73a2cecb7266426842e6697e4e79d9dcf88e5a16 [file] [log] [blame]
Laszlo Csomorcf773d22016-09-15 12:30:46 +00001#!/bin/bash
2#
3# Copyright 2016 The Bazel Authors. All rights reserved.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17set -euo pipefail
18
Laszlo Csomor7224e6b2016-09-16 11:52:36 +000019PLATFORM="$(uname -s | tr 'A-Z' 'a-z')"
20
Laszlo Csomorcf773d22016-09-15 12:30:46 +000021# Print the resolved path of a symbolic link (or the path itself if not a link).
22#
23# The result may be relative to the current working directory and may contain
24# "." and ".." references. Use `normalize_path` to remove those.
25#
26# Fail and print nothing if the input path doesn't exist, i.e. it's a
27# non-existent file, dangling symlink, or circular symlink.
28function resolve_links() {
29 local name="$1"
30
31 if [ -e "$name" ]; then
32 # resolve all links, keep path absolute
33 while [ -L "$name" ]; do
34 local target=$(readlink "$name")
35 if [ "$(echo "$target" | head -c1)" = "/" ]; then
36 name="$target"
37 else
38 name="$(dirname "$name")/$target"
39 fi
40 done
41 echo "$name"
42 else
43 false # fail the function
44 fi
45}
46
47# Normalize a path string by removing "." and ".." references from it.
48#
49# Print the result to stdout.
50#
51# The path doesn't have to point to an existing file.
52function normalize_path() {
53 local name="$1"
54
55 local path=""
56 local uplevels=0
57 while [ "$name" != "/" -a "$name" != "." ]; do
58 local segment="$(basename "$name")"
59 name="$(dirname "$name")"
60
61 [ "$segment" = "." ] && continue
62
63 if [ "$segment" = ".." ]; then
64 uplevels="$((${uplevels}+1))"
65 else
66 if [ "$uplevels" -gt 0 ]; then
67 uplevels="$((${uplevels}-1))"
68 else
69 path="${segment}/${path}"
70 fi
71 fi
72 done
73
74 if [ "$name" = "." ]; then
75 while [ "$uplevels" -gt 0 ]; do
76 path="../$path"
77 uplevels="$((${uplevels}-1))"
78 done
79 fi
80
81 path="${path%/}"
82
83 if [ "$name" = "/" ]; then
84 echo "/$path"
85 else
86 [ -n "$path" ] && echo "$path" || echo "."
87 fi
88}
89
90# Custom implementation of `realpath(1)`.
91#
92# Resolves a symlink to the absolute path it points to. Fails if the link or
93# its target does not exist.
94#
95# Fails and prints nothing if the input path doesn't exist, i.e. it's a
96# non-existent file, dangling symlink, or circular symlink.
97#
98# We use this method instead of `realpath(1)` because the latter is not
99# available on Mac OS X by default.
100function get_real_path() {
101 local name="$1"
102 name="$(resolve_links "$name" || echo)"
103 if [ -n "$name" ]; then
104 normalize_path "$(pwd)/$name"
105 else
106 false # fail the function
107 fi
108}
Laszlo Csomor7224e6b2016-09-16 11:52:36 +0000109
110function md5_file() {
111 if [ $# -gt 0 ]; then
112 local result=""
Klaus Aehligd77c6ea2017-07-05 09:29:20 -0400113 if [[ ${PLATFORM} == "darwin" ]] || [[ ${PLATFORM} == "freebsd" ]]; then
Laszlo Csomor7224e6b2016-09-16 11:52:36 +0000114 result=$(md5 -q $@ || echo)
115 else
116 result=$(md5sum $@ | awk '{print $1}' || echo)
117 fi
118
119 if [ -n "$result" ]; then
120 echo "$result"
121 else
122 false
123 fi
124 else
125 false
126 fi
127}