xref: /aosp_15_r20/external/pigweed/pw_env_setup/util.fish (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1# Copyright 2024 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# This script must be tested on fish 3.6.0
16
17# Note: Colors are unfortunately duplicated in several places; and removing the
18# duplication is not easy. Their locations are:
19#
20#   - bootstrap.sh
21#   - pw_cli/color.py
22#   - pw_env_setup/py/pw_env_setup/colors.py
23#   - pw_env_setup/util.fish
24#   - pw_env_setup/util.sh
25#
26# So please keep them matching then modifying them.
27function pw_none
28    set_color normal
29    echo -e $argv
30end
31
32function pw_red
33    set_color red
34    echo -e $argv
35    set_color normal
36end
37
38function pw_bold_red
39    set_color --bold red
40    echo -e $argv
41    set_color normal
42end
43
44function pw_yellow
45    set_color yellow
46    echo -e $argv
47    set_color normal
48end
49
50function pw_bold_yellow
51    set_color --bold yellow
52    echo -e $argv
53    set_color normal
54end
55
56function pw_green
57    set_color green
58    echo -e $argv
59    set_color normal
60end
61
62function pw_bold_green
63    set_color --bold green
64    echo -e $argv
65    set_color normal
66end
67
68function pw_blue
69    set_color blue
70    echo -e $argv
71    set_color normal
72end
73
74function pw_cyan
75    set_color cyan
76    echo -e $argv
77    set_color normal
78end
79
80function pw_magenta
81    set_color magenta
82    echo -e $argv
83    set_color normal
84end
85
86function pw_bold_white
87    set_color --bold white
88    echo -e $argv
89    set_color normal
90end
91
92function pw_error
93    set_color --bold brred
94    echo -e $argv 1>&2
95    set_color normal
96end
97
98function pw_error_info
99    set_color red
100    echo -e $argv 1>&2
101    set_color normal
102end
103
104# Print an error and exit if $is_sourced == 0 (the first argument).
105function pw_eval_sourced --argument-names is_sourced bootstrap_path
106    if test $is_sourced -eq 0
107        set _PW_NAME (basename $bootstrap_path)
108        pw_error "Error: Attempting to $_PW_NAME in a subshell"
109        pw_error_info "  Since $_PW_NAME modifies your shell's environment"
110        pw_error_info "  variables, it must be sourced rather than executed. In"
111        pw_error_info "  particular, 'fish $_PW_NAME' will not work since the "
112        pw_error_info "  modified environment will get destroyed at the end of the"
113        pw_error_info "  script. Instead, source the script's contents in your"
114        pw_error_info "  shell:"
115        pw_error_info ""
116        pw_error_info "    \$ source $_PW_NAME"
117        exit 1
118    end
119end
120
121# Check for spaces in $_PW_ROOT (the first argument).
122function pw_check_root --argument-names _PW_ROOT
123    if string match --quiet '* *' $_PW_ROOT
124        pw_error "Error: The Pigweed path contains spaces"
125        pw_error_info "  The path '$_PW_ROOT' contains spaces. "
126        pw_error_info "  Pigweed's Python environment currently requires Pigweed to"
127        pw_error_info "  be at a path without spaces. Please checkout Pigweed in a"
128        pw_error_info "  directory without spaces and retry running bootstrap."
129        return -1
130    end
131end
132
133# Check for and return the environment directory location.
134function pw_get_env_root
135    # PW_ENVIRONMENT_ROOT allows callers to specify where the environment should
136    # be installed. bootstrap.sh scripts should not use that variable to store the
137    # result of this function. This separation allows scripts to assume
138    # PW_ENVIRONMENT_ROOT came from the caller and not from a previous bootstrap
139    # possibly from another workspace. PW_ENVIRONMENT_ROOT will be cleared after
140    # environment setup completes.
141    if set --query PW_ENVIRONMENT_ROOT
142        echo $PW_ENVIRONMENT_ROOT
143        return
144    end
145
146    # Determine project-level root directory.
147    if set --query PW_PROJECT_ROOT
148        set _PW_ENV_PREFIX $PW_PROJECT_ROOT
149    else
150        set _PW_ENV_PREFIX $PW_ROOT
151    end
152
153    # If <root>/environment exists, use it. Otherwise, if <root>/.environment
154    # exists, use it. Finally, use <root>/environment.
155    set _PW_DOTENV $_PW_ENV_PREFIX/.environment
156    set _PW_ENV $_PW_ENV_PREFIX/environment
157
158    if test -d $_PW_DOTENV
159        if test -d $_PW_ENV
160            pw_error "Error: both possible environment directories exist."
161            pw_error_info "  $_PW_DOTENV"
162            pw_error_info "  $_PW_ENV"
163            pw_error_info "  If only one of these folders exists it will be used for"
164            pw_error_info "  the Pigweed environment. If neither exists"
165            pw_error_info "  '<...>/environment' will be used. Since both exist,"
166            pw_error_info "  bootstrap doesn't know which to use. Please delete one"
167            pw_error_info "  or both and rerun bootstrap."
168            exit 1
169        end
170    end
171
172    if test -d $_PW_ENV
173        echo $_PW_ENV
174    else if test -d $_PW_DOTENV
175        echo $_PW_DOTENV
176    else
177        echo $_PW_ENV
178    end
179end
180
181
182set --export _PW_BANNER "\
183 ▒█████▄   █▓  ▄███▒  ▒█    ▒█ ░▓████▒ ░▓████▒ ▒▓████▄
184  ▒█░  █░ ░█▒ ██▒ ▀█▒ ▒█░ █ ▒█  ▒█   ▀  ▒█   ▀  ▒█  ▀█▌
185  ▒█▄▄▄█░ ░█▒ █▓░ ▄▄░ ▒█░ █ ▒█  ▒███    ▒███    ░█   █▌
186  ▒█▀     ░█░ ▓█   █▓ ░█░ █ ▒█  ▒█   ▄  ▒█   ▄  ░█  ▄█▌
187  ▒█      ░█░ ░▓███▀   ▒█▓▀▓█░ ░▓████▒ ░▓████▒ ▒▓████▀
188"
189
190function _default_pw_banner_func
191    pw_magenta $_PW_BANNER
192end
193
194set --export _PW_BANNER_FUNC _default_pw_banner_func
195
196function _pw_hello --argument-names _PW_TEXT
197    # If $PW_BANNER_FUNC is defined, use that as the banner function
198    # instead of the default.
199    if set --query PW_BANNER_FUNC
200        set _PW_BANNER_FUNC $PW_BANNER_FUNC
201    end
202    # Display the banner unless PW_ENVSETUP_QUIET or
203    # PW_ENVSETUP_NO_BANNER is set.
204    if test -z "$PW_ENVSETUP_QUIET" && test -z "$PW_ENVSETUP_NO_BANNER"
205        pw_green "\n  WELCOME TO...\n"
206        set_color normal
207        $_PW_BANNER_FUNC
208        set_color normal
209        pw_green $_PW_TEXT
210    end
211end
212
213function pw_deactivate
214    # Assume PW_ROOT and PW_PROJECT_ROOT have already been set and we need to
215    # preserve their values.
216    set _NEW_PW_ROOT $PW_ROOT
217    set _NEW_PW_PROJECT_ROOT $PW_PROJECT_ROOT
218
219    # Find deactivate script, run it, and then delete it. This way if the
220    # deactivate script is doing something wrong subsequent bootstraps still
221    # have a chance to pass.
222    set _PW_DEACTIVATE_SH $_PW_ACTUAL_ENVIRONMENT_ROOT/deactivate.fish
223    if test -f $_PW_DEACTIVATE_SH
224        . $_PW_DEACTIVATE_SH
225        rm -f $_PW_DEACTIVATE_SH &>/dev/null
226    end
227
228    # If there's a _pw_deactivate function run it. Redirect output to /dev/null
229    # in case _pw_deactivate doesn't exist. Remove _pw_deactivate when complete.
230    if functions --query _pw_deactivate
231        _pw_deactivate >/dev/null 2>/dev/null
232        functions -e _pw_deactivate
233    end
234
235    # Restore.
236    set --export PW_ROOT $_NEW_PW_ROOT
237    set --export PW_PROJECT_ROOT $_NEW_PW_PROJECT_ROOT
238end
239
240function deactivate
241    pw_deactivate
242    functions -e pw_deactivate
243    functions -e deactivate
244    set -e PW_ROOT
245    set -e PW_PROJECT_ROOT
246    set -e PW_BRANDING_BANNER
247    set -e PW_BRANDING_BANNER_COLOR
248end
249
250# The next three functions use the following variables.
251# * PW_BANNER_FUNC: function to print banner
252# * PW_BOOTSTRAP_PYTHON: specific Python interpreter to use for bootstrap
253# * PW_ROOT: path to Pigweed root
254# * PW_ENVSETUP_QUIET: limit output if "true"
255#
256# All arguments passed in are passed on to env_setup.py in pw_bootstrap,
257# pw_activate takes no arguments, and pw_finalize takes the name of the script
258# "bootstrap" or "activate" and the path to the setup script written by
259# bootstrap.fish.
260function pw_bootstrap
261    _pw_hello "  BOOTSTRAP! Bootstrap may take a few minutes; please be patient.\n"
262
263    if functions --query python
264        pw_error "Error: 'python' is an alias"
265        pw_error_info "The shell has a 'python' alias set. This causes many obscure"
266        pw_error_info "Python-related issues both in and out of Pigweed. Please"
267        pw_error_info "remove the Python alias from your shell init file or at"
268        pw_error_info "least run the following command before bootstrapping"
269        pw_error_info "Pigweed."
270        pw_error_info
271        pw_error_info "  functions --erase python"
272        pw_error_info
273        return
274    end
275
276    # Allow forcing a specific version of Python for testing pursposes.
277    if test -n "$PW_BOOTSTRAP_PYTHON"
278        set _PW_PYTHON "$PW_BOOTSTRAP_PYTHON"
279    else if command -v python3 >/dev/null 2>/dev/null
280        set _PW_PYTHON python3
281    else if command -v python >/dev/null 2>/dev/null
282        set _PW_PYTHON python
283    else
284        pw_error "Error: No system Python present\n"
285        pw_error_info "  Pigweed's bootstrap process requires a local system"
286        pw_error_info "  Python. Please install Python on your system, add it to "
287        pw_error_info "  your PATH and re-try running bootstrap."
288        return
289    end
290
291    if test -n "$_PW_ENV_SETUP"
292        $_PW_ENV_SETUP $argv
293        set _PW_ENV_SETUP_STATUS $status
294    else
295        $_PW_PYTHON $PW_ROOT/pw_env_setup/py/pw_env_setup/env_setup.py $argv
296        set _PW_ENV_SETUP_STATUS $status
297    end
298
299    # Write the directory path at bootstrap time into the directory. This helps
300    # us double-check things are still in the same space when calling activate.
301    set _PW_ENV_ROOT_TXT $_PW_ACTUAL_ENVIRONMENT_ROOT/env_root.txt
302    echo $_PW_ACTUAL_ENVIRONMENT_ROOT >$_PW_ENV_ROOT_TXT 2>/dev/null
303
304    # Create the environment README file. Use quotes to prevent alias expansion.
305    cp $PW_ROOT/pw_env_setup/destination.md $_PW_ACTUAL_ENVIRONMENT_ROOT/README.md &>/dev/null
306end
307
308function pw_activate_message
309    _pw_hello "  ACTIVATOR! This sets your shell environment variables.\n"
310    set _PW_ENV_SETUP_STATUS 0
311end
312
313function pw_finalize_pre_check --argument-names _PW_NAME _PW_SETUP_SH
314    # Check that the environment directory agrees that the path it's at matches
315    # where it thinks it should be. If not, bail.
316    set _PW_ENV_ROOT_TXT "$_PW_ACTUAL_ENVIRONMENT_ROOT/env_root.txt"
317    if test -f $_PW_ENV_ROOT_TXT
318        set _PW_PREV_ENV_ROOT (cat $_PW_ENV_ROOT_TXT)
319        if test "$_PW_ACTUAL_ENVIRONMENT_ROOT" != "$_PW_PREV_ENV_ROOT"
320            pw_error "Error: Environment directory moved"
321            pw_error_info "This Pigweed environment was created at"
322            pw_error_info
323            pw_error_info "    $_PW_PREV_ENV_ROOT"
324            pw_error_info
325            pw_error_info "But it is now being activated from"
326            pw_error_info
327            pw_error_info "    $_PW_ACTUAL_ENVIRONMENT_ROOT"
328            pw_error_info
329            pw_error_info "This is likely because the checkout moved. After moving "
330            pw_error_info "the checkout a full '. ./bootstrap.fish' is required."
331            pw_error_info
332            set _PW_ENV_SETUP_STATUS 1
333        end
334    end
335
336    if test -n "$_PW_ENV_SETUP_STATUS" && test "$_PW_ENV_SETUP_STATUS" -ne 0
337        return
338    end
339
340    if not test -f "$_PW_SETUP_SH"
341        pw_error "Error during $_PW_NAME--see messages above."
342    end
343end
344
345function pw_finalize_post_check --argument-names _PW_NAME _PW_SETUP_SH
346    if test "$status" -eq 0
347        if test "$_PW_NAME" = bootstrap && test -z "$PW_ENVSETUP_QUIET"
348            echo "To reactivate this environment in the future, run this in your "
349            echo "terminal:"
350            echo
351            pw_green "  source ./activate.fish"
352            echo
353            echo "To deactivate this environment, run this:"
354            echo
355            pw_green "  deactivate"
356            echo
357        end
358    else
359        pw_error "Error during $_PW_NAME--see messages above."
360    end
361end
362
363function pw_install_post_checkout_hook
364    cp $PW_ROOT/pw_env_setup/post-checkout-hook.sh $PW_PROJECT_ROOT/.git/hooks/post-checkout
365end
366
367function pw_cleanup
368    set -e _PW_BANNER
369    set -e _PW_BANNER_FUNC
370    set -e PW_BANNER_FUNC
371    set -e _PW_ENV_SETUP
372    set -e _PW_NAME
373    set -e PW_ENVIRONMENT_ROOT
374    set -e _PW_PYTHON
375    set -e _PW_ENV_ROOT_TXT
376    set -e _PW_PREV_ENV_ROOT
377    set -e _PW_SETUP_SH
378    set -e _PW_DEACTIVATE_SH
379    set -e _NEW_PW_ROOT
380    set -e _PW_ENV_SETUP_STATUS
381    set -e _PW_ENV_PREFIX
382    set -e _PW_ENV
383    set -e _PW_DOTENV
384
385    functions -e pw_none
386    functions -e pw_red
387    functions -e pw_bold_red
388    functions -e pw_yellow
389    functions -e pw_bold_yellow
390    functions -e pw_green
391    functions -e pw_bold_green
392    functions -e pw_blue
393    functions -e pw_cyan
394    functions -e pw_magenta
395    functions -e pw_bold_white
396    functions -e pw_eval_sourced
397    functions -e pw_check_root
398    functions -e pw_get_env_root
399    functions -e _pw_banner
400    functions -e pw_bootstrap
401    functions -e pw_activate
402    functions -e pw_finalize
403    functions -e pw_install_post_checkout_hook
404    functions -e pw_cleanup
405    functions -e _pw_hello
406    functions -e pw_error
407    functions -e pw_error_info
408end
409