-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathjust
executable file
·334 lines (306 loc) · 12 KB
/
just
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
#!/usr/bin/env bash
#*# just/just
#**
# .. default-domain:: bash
#
# .. _just:
#
# ========
# J.U.S.T.
# ========
#
# .. file:: just
#
# When working on a project, it often becomes necessary to run many long commands. Similar to how a makefile connects `targets` with a string of commands, `just` gives an easy way to create a set of targets to execute easily. Unlike a makefile, it has two key distinctions
#
# * It's not a makefile, but uses a :file:`Justfile` in bash instead. Bash is easier than make for simple tasks
# * It works on Windows (when bash is installed via Git for Windows or similar), macOS (which uses bash 3.2) and Linux with no additional dependencies.
#
# .. rubric:: Features
#
# * Tab completion (:file:`.just`)
# * Comment generated help
# * Subcommands (e.g. ``just program run``, run can be a subcommand of the program target)
# * Executing multiple targets in one call
#
# .. seealso::
#
# :file:`Justfile`
# Blah justfile
#
# :file:`.just`
# Tab completion for bash
#**
#**
# .. command:: help
#
# Print out basic help based on the comments it the :file:`Justfile`. In order to achieve this, case statements and comments need to be structured in a specific way for the parser to pick up. The same mechanism is used by tab completion in ``bash``
#
# .. note::
#
# Currently this does not work for all ``bash`` cases. A few bash patterns are matched to make this behavior working, since bash does not have source reflection.
#
# .. rubric:: Basic example:
#
# In the simplest case, a regular case pattern followed by ``)#`` (with optional spaces) will be picked up by :cmd:`help`
#
# .. code-block:: bash
#
# foo) # Runs the foo routine
#
# .. rubric:: Long comment lines
#
# A long comment can be split up into many lines by ending a line with ``\`` (that means no space after ``\``), and the comment on the next line continue.
#
# .. code-block:: bash
#
# command) # To write a long help message, end the line in a backslash (\) \
# # and start the next line with a # to continue the comment. \
# # Can be as long as you want.
#
# .. rubric:: Multiple targets at once:
#
# The pattern ``pattern1|pattern2...)#`` will also be parsed as a single help entry
#
# .. code-block:: bash
#
# cat|dog) # Routine for cats and dogs
#
# .. rubric:: Multiple targets:
#
# You can actually add any of the other patterns as a comment for the sole purpose of populating the help and tab completion
#
# .. code-block:: bash
#
# # cat) # Comment just for cat
# # dog) # Comment just for dog
# cat|\
# dog) # A comment here would be for both cat and dog, but not needed
#
# .. rubric:: Subcommand example:
#
# .. code-block:: bash
#
# foo_cat) # Runs the foo routine for cat
# foo_dog) # Runs the foo routine for dog
#
# .. rubric:: Commenting extra help subcommand:
#
# .. code-block:: bash
#
# # foo_a) # Runs the foo routine for a
# # foo_b) # Runs the foo routine for b
# foo_*)
# ## foo_c) # Runs the foo routine for c, but don't tell anyone
#
# The foo_a and foo_b are added to tab complete and help, but using more than one `#` will disable that line all together. So foo_c is ignored and does not show up in help or tab complete.
#
# .. rubric:: Advanced Expansion subcommand array:
#
# When you have a list of subcommands for a command in an array, then that can use that array to generate help/tab completion entries
#
# .. code-block:: bash
#
# # Example array
# MY_ARRAY=(cat dog)
#
# ...
#
# # catch_{MY_ARRAY}) #Catch animal
# catch_*)
#
# Help, tab complete, etc. will automatically be expanded to cat and dog. Very useful for *DRY* and for programmatically determined subtargets. The subtarget name is appended to the end of the comment. So this example will read
#
# ::
#
# catch
# cat - Catch animal cat
# dog - Catch animal dog
#
# .. note::
#
# Help and tab completion use the exact same mechanism. Everything that adds an entry to the help is adding an entry to tab completion.
#**
#**
# .. envvar:: JUST_PRELOAD
#
# Preloads a special source file before anything else loads.
#
# In rare case that the project environment file is too late in the just loading, use this file. It is suggested to set the value in the :envvar:`JUST_SETUP_SCRIPT`, which defaults to setup.env.
#
# .. note::
#
# This is left around for debug purposes really, probably never needed.
#
# .. note::
#
# Must **not** be set in the :ref:`project environment files <just-project-env-files>` i.e. cannot be set in ``local.env``, project env file or ``local_post.env``. It will **not** have the desired effect, as this is too late in the load chain. Instead, it can either be exported before calling :file:`just` (not recommended unless in a container or VM) or exported in the :ref:`setup file <just-setup-file>`.
#**
#**
# .. envvar:: JUST_VERBOSE
#
# :Values: * **1** - Prints any dryrun-able commands as they are executed
# * **2** - Basic bash verbose. Uses ``set -v``
# * **3** - Fully verbose. ``set -xv`` plus a useful ``PS4``
#
# :envvar:`JUST_VERBOSE` sets verbosity level of just execution. Useful to debug problems, especially in the just executable.
#
# .. note::
#
# Must **not** be set in the :ref:`project environment files <just-project-env-files>` i.e. cannot be set in ``local.env``, project env file or ``local_post.env``. It will **not** have the desired effect, as this is too late in the load chain. Instead, it can either be exported before calling :file:`just` (not recommended unless in a container or VM) or exported in the :ref:`setup file <just-setup-file>`.
#**
function print_error()
{
local rv="${?}" # This must be the first line
#**
# ..envvar:: JUST_IGNORE_EXIT_CODES
#
# A regular expression that represents exit codes that will result in a just stack trace not being printed out. This is good for handling errors that are expected to happen, and do not need a misleading stack track when you know the problem is a known issue, like a missing file, etc... Default: ``0``, (disabled).
#
# .. rubric:: Examples:
#
# .. code-block:: bash
#
# # Justfile example
# just_target)
# local JUST_IGNORE_EXIT_CODES=2
# bash -c "exit 2"
# ;;
#
# # More example values
# 25 # Only 25 is ignored
# 24$|^25 # 24 or 25 is ignored; ^ is implied at the beginning and $ at the end. So it is really: "^24$|^25$"
# 2. # 20-29
# .* # All exit codes
# 3.$|^72 # 30-39 or 72
# $|5|^ # Any code with a 5 in it, 5, 15, 25... 50-59, etc
#**
if [[ ${rv} =~ ^${JUST_IGNORE_EXIT_CODES-0}$ ]]; then
return
fi
set +E
echo >&2
print_bash_stack 1
echo >&2
echo "${1}: line ${2}: Returned ${rv}" >&2
}
#**
# .. envvar:: JUST_IN_SCRIPT
#
# :envvar:`JUST_IN_SCRIPT` is an unexported variable set by :file:`just`. Useful in other scripts for determining if they are being sourced by :file:`just` or not.
#
# Currently one use of this is dual purposing a file, so that it behaves differently when sourced by just or by a user on the prompts
#**
if [ -z "${VSI_COMMON_DIR+set}" ]; then
VSI_COMMON_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.."; pwd)"
fi
# Activate source_once, should be the first file loaded, for maximum benefit
source "${VSI_COMMON_DIR}/linux/source_once.bsh"
# Speed up dirname/basename
source "${VSI_COMMON_DIR}/linux/dir_tools.bsh"
source "${VSI_COMMON_DIR}/linux/just_files/just_functions.bsh"
source "${VSI_COMMON_DIR}/linux/bash_utils.bsh"
#**
# .. envvar:: JUST_USER_CWD
#
# Although :file:`just` does not have to be run from the just project's root directory, some commands (e.g., ``docker compose``, but also parts of ``just`` proper) expect to be run from the project's root directory. Typically, the :file:`Justfile` will ``cd`` from the current working directory to the project's root directory, as specified by ``${PROJECT_PREFIX}_CWD`` (thereafter the project's CWD). :envvar:`JUST_USER_CWD` tracks the working directory from which a ``just`` command was run.
#**
#**
# .. envvar:: JUSTFILE
#
# An optional variable for the location of :file:`Justfile`. The default :file:`Justfile` that :func:`just_common.bsh _just_load_justfile` searches for is called ``Justfile``. In order to change this default behavior, this environment variable needs to be set so that :file:`just` knows what file name to look for, usually not recommended
#
# .. seealso::
#
# :func:`just_common.bsh _just_load_justfile`
# Function responsible for loading :file:`Justfile`
#
# :func:`dir_tools.bsh parent_find_files`
# Function responsible for finding :file:`Justfile`
#
# :envvar:`JUSTFILE`
# Changes the name of the default :file:`Justfile` to a different filename when creating a new project
#
# .. note::
#
# Must **not** be set in the :ref:`project environment files <just-project-env-files>` i.e. cannot be set in ``local.env``, project env file or ``local_post.env``. It will **not** have the desired effect, as this is too late in the load chain. Instead, it can either be exported before calling :file:`just` (not recommended unless in a container or VM) or exported in the :ref:`setup file <just-setup-file>`.
#**
function just()
{
if [ -e "${JUST_PRELOAD-}" ]; then
source "${JUST_PRELOAD}"
fi
set -euE
if [ "${JUST_VERBOSE-}" = "1" ]; then
function print_and_run()
{
print_command just --wrap ${@+"${@}"} >&2
${@+"${@}"}
}
DRYRUN=print_and_run
elif [ "${JUST_VERBOSE-}" = "2" ]; then
set -v
elif [ "${JUST_VERBOSE-}" = "3" ]; then
PS4='+${BASH_SOURCE[0]}:${LINENO} '
set -xv
fi
trap 'print_error "${BASH_SOURCE[0]}" "${LINENO}"' ERR
JUST_IN_SCRIPT=1
setup_tty ${@+"${@}"}
if [ "${JUST_RODEO-}" = "1" ]; then
: ${JUST_USER_CWD=${USER_PWD}}
else
: ${JUST_USER_CWD=${PWD}}
fi
export JUST_USER_CWD
: ${JUSTFILE=Justfile}
# Solve #130
if [ "${JUSTFILE:0:1}" = "." ]; then
JUSTFILE="$(real_path "${JUSTFILE}")"
fi
# Covers certain corner cases, like Just_wrap
unset JUST_SETTINGS
if ! _just_load_justfile "${JUSTFILE}"; then
JUST_FILE_NOT_FOUND=1
fi
# Move this check here, so that if there are multiple JUST_SETTINGS, or other
# advanced setups, that what ever is set when it is all done being loaded is
# what really counts.
check_just_version
if [ "${1-}" != "_null" ]; then
justify ${@+"${@}"}
fi
}
if [ "${BASH_SOURCE[0]}" = "${0}" ] || [ "$(basename "${BASH_SOURCE[0]}")" = "${0}" ]; then
just ${@+"${@}"}
fi
#**
# Error handling
# --------------
#
# An error in a :file:`Justfile` can be extremely hard to debug. Especially when the bug manifests itself deep inside :file:`just`. For this reason, it is customary to turn ``set -eu`` on, so that if a bash command returns false, the script stops. (``-u`` says that if a variable is used without being defined, to throw and error too).
#
# The ``ERR`` signal is also trapped by :file:`just`. When any error occurs, a complete bash stack trace is printed to stdout upon exit.
#
# ::
#
# Call stack
# ----------
# 993 _Docker /opt/projects/just/vsi_common/linux/just_files/docker_functions.bsh
# 974 Docker /opt/projects/just/vsi_common/linux/just_files/docker_functions.bsh
# 120 caseify /opt/projects/just/vsi_common/Justfile
# 795 justify /opt/projects/just/vsi_common/linux/just_files/just_functions.bsh
# 281 main /opt/projects/just/vsi_common/linux/just
#
# /opt/projects/just/vsi_common/linux/just_files/docker_functions.bsh: line 993: Returned 2
#
# Call stack
# ----------
# 21 caseify /opt/projects/just/vsi_common/Justfile
# 795 justify /opt/projects/just/vsi_common/linux/just_files/just_functions.bsh
# 281 main /opt/projects/just/vsi_common/linux/just
#
# /opt/projects/just/vsi_common/Justfile: line 21: Returned 2
#
# Sometimes there are multiple stacks due to the way `bash` works. However the first one is usually the stack of interest. This stack printout says an error occurred in ``_Docker`` line 993, and can be tracked down to ``Justfile`` line 120. In this case, a ``docker`` command returned non-zero
#**