1# Copyright 2020 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7#     https://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, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14
15# Just in case PATH isn't already exported.
16export PATH
17
18# Note: Colors are unfortunately duplicated in several places; and removing the
19# duplication is not easy. Their locations are:
20#
21#   - bootstrap.sh
22#   - pw_cli/color.py
23#   - pw_env_setup/py/pw_env_setup/colors.py
24#
25# So please keep them matching then modifying them.
26pw_none() {
27  echo -e "$*"
28}
29
30pw_red() {
31  echo -e "\033[0;31m$*\033[0m"
32}
33
34pw_bold_red() {
35  echo -e "\033[1;31m$*\033[0m"
36}
37
38pw_yellow() {
39  echo -e "\033[0;33m$*\033[0m"
40}
41
42pw_bold_yellow() {
43  echo -e "\033[1;33m$*\033[0m"
44}
45
46pw_green() {
47  echo -e "\033[0;32m$*\033[0m"
48}
49
50pw_bold_green() {
51  echo -e "\033[1;32m$*\033[0m"
52}
53
54pw_blue() {
55  echo -e "\033[1;34m$*\033[0m"
56}
57
58pw_cyan() {
59  echo -e "\033[1;36m$*\033[0m"
60}
61
62pw_magenta() {
63  echo -e "\033[0;35m$*\033[0m"
64}
65
66pw_bold_white() {
67  echo -e "\033[1;37m$*\033[0m"
68}
69
70pw_eval_sourced() {
71  if [ "$1" -eq 0 ]; then
72    # TODO(pwbug/354) Remove conditional after all downstream projects have
73    # changed to passing in second argument.
74    if [ -n "$2" ]; then
75      _PW_NAME=$(basename "$2" .sh)
76    else
77      _PW_NAME=$(basename "$_BOOTSTRAP_PATH" .sh)
78    fi
79    pw_bold_red "Error: Attempting to $_PW_NAME in a subshell"
80    pw_red "  Since $_PW_NAME.sh modifies your shell's environment variables,"
81    pw_red "  it must be sourced rather than executed. In particular, "
82    pw_red "  'bash $_PW_NAME.sh' will not work since the modified "
83    pw_red "  environment will get destroyed at the end of the script. "
84    pw_red "  Instead, source the script's contents in your shell:"
85    pw_red ""
86    pw_red "    \$ source $_PW_NAME.sh"
87    exit 1
88  fi
89}
90
91pw_check_root() {
92  _PW_ROOT="$1"
93  if [[ "$_PW_ROOT" = *" "* ]]; then
94    pw_bold_red "Error: The Pigweed path contains spaces\n"
95    pw_red "  The path '$_PW_ROOT' contains spaces. "
96    pw_red "  Pigweed's Python environment currently requires Pigweed to be "
97    pw_red "  at a path without spaces. Please checkout Pigweed in a "
98    pw_red "  directory without spaces and retry running bootstrap."
99    return
100  fi
101}
102
103pw_get_env_root() {
104  # PW_ENVIRONMENT_ROOT allows developers to specify where the environment
105  # should be installed. bootstrap.sh scripts should not use that variable to
106  # store the result of this function. This separation allows scripts to assume
107  # PW_ENVIRONMENT_ROOT came from the developer and not from a previous
108  # bootstrap possibly from another workspace.
109  if [ -z "$PW_ENVIRONMENT_ROOT" ]; then
110    if [ -n "$PW_PROJECT_ROOT" ]; then
111      echo "$PW_PROJECT_ROOT/.environment"
112    else
113      echo "$PW_ROOT/.environment"
114    fi
115  else
116    echo "$PW_ENVIRONMENT_ROOT"
117  fi
118}
119
120# Note: This banner is duplicated in three places; which is a lesser evil than
121# the contortions that would be needed to share this snippet across shell,
122# batch, and Python. Locations:
123#
124#   - pw_env_setup/util.sh
125#   - pw_cli/branding.py
126#   - pw_env_setup/py/pw_env_setup/windows_env_start.py
127#
128_PW_BANNER=$(cat <<EOF
129 ▒█████▄   █▓  ▄███▒  ▒█    ▒█ ░▓████▒ ░▓████▒ ▒▓████▄
130  ▒█░  █░ ░█▒ ██▒ ▀█▒ ▒█░ █ ▒█  ▒█   ▀  ▒█   ▀  ▒█  ▀█▌
131  ▒█▄▄▄█░ ░█▒ █▓░ ▄▄░ ▒█░ █ ▒█  ▒███    ▒███    ░█   █▌
132  ▒█▀     ░█░ ▓█   █▓ ░█░ █ ▒█  ▒█   ▄  ▒█   ▄  ░█  ▄█▌
133  ▒█      ░█░ ░▓███▀   ▒█▓▀▓█░ ░▓████▒ ░▓████▒ ▒▓████▀
134EOF
135)
136
137_pw_banner() {
138  if [ -z "$PW_ENVSETUP_QUIET" ] && [ -z "$PW_ENVSETUP_NO_BANNER" ]; then
139    pw_magenta "$_PW_BANNER\n"
140  fi
141}
142
143_PW_BANNER_FUNC="_pw_banner"
144
145_pw_hello() {
146  _PW_TEXT="$1"
147  if [ -n "$PW_BANNER_FUNC" ]; then
148    _PW_BANNER_FUNC="$PW_BANNER_FUNC"
149  fi
150  if [ -z "$PW_ENVSETUP_QUIET" ]; then
151    pw_green "\n  WELCOME TO...\n"
152    "$_PW_BANNER_FUNC"
153    pw_green "$_PW_TEXT"
154  fi
155}
156
157pw_deactivate() {
158  # Assume PW_ROOT and PW_PROJECT_ROOT has already been set and we need to
159  # preserve their values.
160  _NEW_PW_ROOT="$PW_ROOT"
161  _NEW_PW_PROJECT_ROOT="$PW_PROJECT_ROOT"
162
163  # Find deactivate script and run it.
164  _PW_DEACTIVATE_SH="$_PW_ACTUAL_ENVIRONMENT_ROOT/deactivate.sh"
165  if [ -f "$_PW_DEACTIVATE_SH" ]; then
166    . "$_PW_DEACTIVATE_SH"
167  fi
168
169  # If there's a _pw_deactivate function run it. Redirect output to /dev/null
170  # in case _pw_deactivate doesn't exist.
171  if [ -n "$(command -v _pw_deactivate)" ]; then
172    _pw_deactivate &> /dev/null
173  fi
174
175  # Restore.
176  PW_ROOT="$_NEW_PW_ROOT"
177  export PW_ROOT
178  PW_PROJECT_ROOT="$_NEW_PW_PROJECT_ROOT"
179  export PW_PROJECT_ROOT
180}
181
182# The next three functions use the following variables.
183# * PW_BANNER_FUNC: function to print banner
184# * PW_BOOTSTRAP_PYTHON: specific Python interpreter to use for bootstrap
185# * PW_USE_GCS_ENVSETUP: attempt to grab env setup executable from GCS if "true"
186# * PW_ROOT: path to Pigweed root
187# * PW_ENVSETUP_QUIET: limit output if "true"
188#
189# All arguments passed in are passed on to env_setup.py in pw_bootstrap,
190# pw_activate takes no arguments, and pw_finalize takes the name of the script
191# "bootstrap" or "activate" and the path to the setup script written by
192# bootstrap.sh.
193pw_bootstrap() {
194  _pw_hello "  BOOTSTRAP! Bootstrap may take a few minutes; please be patient.\n"
195
196  # Allow forcing a specific version of Python for testing pursposes.
197  if [ -n "$PW_BOOTSTRAP_PYTHON" ]; then
198    _PW_PYTHON="$PW_BOOTSTRAP_PYTHON"
199  elif which python &> /dev/null; then
200    _PW_PYTHON=python
201  elif which python3 &> /dev/null; then
202    _PW_PYTHON=python3
203  elif which python2 &> /dev/null; then
204    _PW_PYTHON=python2
205  else
206    pw_bold_red "Error: No system Python present\n"
207    pw_red "  Pigweed's bootstrap process requires a local system Python."
208    pw_red "  Please install Python on your system, add it to your PATH"
209    pw_red "  and re-try running bootstrap."
210    return
211  fi
212
213  if [ -n "$PW_USE_GCS_ENVSETUP" ]; then
214    _PW_ENV_SETUP="$("$PW_ROOT/pw_env_setup/get_pw_env_setup.sh")"
215  fi
216
217  if [ -n "$_PW_ENV_SETUP" ]; then
218    "$_PW_ENV_SETUP" "$@"
219    _PW_ENV_SETUP_STATUS="$?"
220  else
221    "$_PW_PYTHON" "$PW_ROOT/pw_env_setup/py/pw_env_setup/env_setup.py" "$@"
222    _PW_ENV_SETUP_STATUS="$?"
223  fi
224}
225
226pw_activate() {
227  _pw_hello "  ACTIVATOR! This sets your shell environment variables.\n"
228  _PW_ENV_SETUP_STATUS=0
229}
230
231pw_finalize() {
232  _PW_NAME="$1"
233  _PW_SETUP_SH="$2"
234
235  if [ "$_PW_ENV_SETUP_STATUS" -ne 0 ]; then
236     return
237  fi
238
239  if [ -f "$_PW_SETUP_SH" ]; then
240    . "$_PW_SETUP_SH"
241
242    if [ "$?" -eq 0 ]; then
243      if [ "$_PW_NAME" = "bootstrap" ] && [ -z "$PW_ENVSETUP_QUIET" ]; then
244        echo "To activate this environment in the future, run this in your "
245        echo "terminal:"
246        echo
247        pw_green "  source ./activate.sh\n"
248      fi
249    else
250      pw_red "Error during $_PW_NAME--see messages above."
251    fi
252  else
253    pw_red "Error during $_PW_NAME--see messages above."
254  fi
255}
256
257pw_cleanup() {
258  unset _PW_BANNER
259  unset _PW_BANNER_FUNC
260  unset _PW_ENV_SETUP
261  unset _PW_NAME
262  unset _PW_PYTHON
263  unset _PW_SETUP_SH
264  unset _PW_DEACTIVATE_SH
265  unset _NEW_PW_ROOT
266  unset _PW_ENV_SETUP_STATUS
267
268  unset pw_none
269  unset pw_red
270  unset pw_bold_red
271  unset pw_yellow
272  unset pw_bold_yellow
273  unset pw_green
274  unset pw_bold_green
275  unset pw_blue
276  unset pw_cyan
277  unset pw_magenta
278  unset pw_bold_white
279  unset pw_eval_sourced
280  unset pw_check_root
281  unset pw_get_env_root
282  unset _pw_banner
283  unset pw_bootstrap
284  unset pw_activate
285  unset pw_finalize
286  unset _pw_cleanup
287}
288