Functions

just_functions.bsh

A few functions are defined in a common. Sourced here for DRY

DRYRUN

Print out some commands instead of executing.

${DRYRUN} <command>

Display key commands as they would be executed. This is conveniently set by using the -n/--dryrun argument. Default: <Null>

Example

function Docker()
{
  ${DRYRUN} docker "${@}"
}

Note

DRYRUN doesn’t just echo out the command, it uses the print_command print_command function to print out a command that can be copied and pasted in. This handles spaces correctly unlike echo.

JUST_SEPARATOR

Separator used for just_functions.bsh get_args

When passing an unknown number of arguments, the JUST_SEPARATOR can be used to begin and end a group of arguments. Default: –

JUST_SAFE_LOAD_DELIMITER

Separator used for safe_load

safe_load reads a key:value file, and this variable is used to separate the keys and values. Default: =

See also

safe_load

just_plugins

Plugin system for just

Usage

Certain just targets can be used for many different projects, and rather then repeating this code, just_plugins give a way to expose the common code of these targets to many different projects.

To add plugins to your project, simply add the plugin filenames to your .justplugins file.

When writing a new plugin, you need to follow a few rules:

  1. A case statement in a defaultify function must be written. The case statement should have a unique name that is not likely to be used anywhere else. All plugin functions have to exist in the same namespace.

  2. Add the case names to the array JUST_DEFAULTIFY_FUNCTIONS to allow the commonly used functionality to be added as targets for just

  3. Add the plugin filename to the array JUST_HELP_FILES

  4. Must return non-zero if the argument is not matched, and return 0 on target match

Example

Source code of a just_example_functions.bsh, which looks something like:

JUST_DEFAULTIFY_FUNCTIONS+=(just_example_defaultify)
JUST_HELP_FILES+=("${BASH_SOURCE[0]}")
function just_example_defaultify()
{
  arg="${1}"
  shift 1
  case "${arg}" in
    foo|bar) #Foobar test
      echo "Foo or bar: ${1}"
      extra_args=1
      ;;
    *)
      plugin_not_found=1
      ;;
  esac
  return 0
}
JUST_PLUGIN_FILE

Name of the just plugin file

Defaults to .justplugins in the same directory as the Justfile, but can be overridden to another filename/path by exporting this variable

Note

Since plugins are loaded right before the project environment, you can not set the JUST_PLUGIN_FILE in the project env file. If you are using a custom JUST_PLUGIN_FILE, it will need to be set in the setup.env

See also

just safe_env

JUST_DEFAULTIFY_FUNCTIONS

List of defaultify functions

The values of this array are executed as a command. Each plugin should have a unique name for the function, and is responsible for adding that function name to JUST_DEFAULTIFY_FUNCTIONS

JUST_HELP_FILES

This should include just_functions.bsh, the Justfile, and any plugins. The plugin is responsible for adding itself to this array.

Usage

Every project should have a setup file, typically called setup.env. This script’s location is stored in JUST_SETUP_SCRIPT and is also where JUST_HELP_FILES should be set.

JUST_PROJECT_PREFIX

Variable prefix for project

Some just functions need to know the prefix used for a project’s environment variables (e.g., in order to list all project env variables using compgen). This should be defined in your project’s settings env file, and does not need to be overridable.

JUST_SETTINGS

Absolute path to the project settings env file; set automatically when you source just_env

JUST_SETTINGS is set automatically by just_env, which is used to setup the project’s environment by sourcing the projects settings env file very early in the project’s Justfile.

Example

Typically, the Justfile will include a line like this very near the top:

source "${VSI_COMMON_DIR}/linux/just_files/just_env" "$(dirname "${BASH_SOURCE[0]}")"/'my_project.env'

Note

JUST_SETTINGS supports multiple files using the JUST_SETTINGS_SEPARATOR (default: ///). The user and developer should not need to come up with this themselves, as it is automatically generated, unless they are manually overriding it.

JUST_SETTINGS_SEPARATOR

Separator used between filenames of JUST_SETTINGS

source_environment_files

Convenience function for sourcing environments

The just system works by sourcing environment files, aka settings files, and plugins

  1. First, ${project_dir}/local.env. This file should never be added to version control. It should contain customizations for that particular install.

  2. Then, the project’s settings env file. This file should ideally contain all the default values necessary to run without any local.env settings.

  3. Last, ${project_dir}/local_post.env. This file should never be added to version control. It is rarely used, except in situations where the value of a variable is based off of another variable. This is why it is loaded last.

  4. Any plugins that are identified, are also sourced

Arguments:

$1 - The project settings filename (e.g., vsi_common.env)

Parameters:
  • [JUST_LOCAL_SETTINGS] - Path to the local settings file. Default: ${same_dir}/local.env

  • [JUST_LOCAL_SETTINGS_POST] - Path to the post local settings file. Default: ${same_dir}/local_post.env

Usage

JUST_LOCAL_SETTINGS and JUST_LOCAL_SETTINGS_POST must not be set in any of the the project’s settings files or plugins, as it will not have the desired effect. Instead, they should either be manually set in the environment or set in the setup script (see JUST_SETUP_SCRIPT)

Note

Certain exceptions to not storing values in the project settings file make sense such as credentials, encryption keys, etc… information that should not be hard-coded ever.

Only require settings in local.env when it cannot be avoided. For example, it might be reasonable to use openssl to create ssl certs in a default location (that is ignored by version control).

create_local_settings_file
Arguments:

$1 - Path to the settings file

Parameters:

[JUST_LOCAL_SETTINGS] - The location to create the local settings file [JUST_LOCAL_SETTINGS_POST] - The location to create the post local local settings file

Return Value:
  • 0 - Settings file was created

  • 1 - Settings file was not created

Output:

[JUST_LOCAL_SETTINGS] - Path to the local settings file. Default: ${same_dir}/local.env [JUST_LOCAL_SETTINGS_POST] - Path to the post local settings file. Default: ${same_dir}/local_post.env

Try to create the local.env settings file

Create the local.env settings file if a) it does not already exist and b) it will be owned by the correct user.

translate_just_settings

Convert JUST_SETTINGS to an array: JUST_SETTINGSS, translating the paths to another filesystem

Arguments:
  • $1 - Directory name to be translated from

  • $2 - Directory name to translate to

Output:

JUST_SETTINGSS - Array of the translated paths

Useful for translating JUST_SETTINGS from host to a container.

auto_path_escape

Automatically add an escape character to paths that match a pattern

TODO: Explain

See also

just_env

set_temp_array
Arguments:
  • $1 - Name of array to check if it is already set

  • $2... - Default values of the array

Output:

JUST_TEMP_ARRAY - Destination for all the values set

DEPRECATED: Set array to default values if not already set.

In bash, when setting a variable to a default value if it has not already been set, it is typical to follow the pattern:

: ${MY_VAR=default}

However, this syntax does not work for an array. Bash 3.2 does not give an equivalent one line version of this. Instead, using set_temp_array, JUST_TEMP_ARRAY can be set to a default value if not already set (albeit, in two lines).

It works by checking if an array is set. If it is, it copies all the values to the array JUST_TEMP_ARRAY. If it is not, it will copy the rest of the arguments (the default values) to JUST_TEMP_ARRAY. When using this function with set -u turned on, it is best to reference JUST_TEMP_ARRAY by (${JUST_TEMP_ARRAY[@]+”${JUST_TEMP_ARRAY[@]}”}) in case the array is empty, as this triggers bash’s unbound variable test.

Example

set_temp_array MY_ARRAY default1 default\ 2 "default 3"
MY_ARRAY=(${JUST_TEMP_ARRAY[@]+"${JUST_TEMP_ARRAY[@]}"})

# And when done, clean up
unset JUST_TEMP_ARRAY
set_array_default
Arguments:

$1 - Name of array to check if it is already set

$2... - Default values of the array

Set array to default values if not already set.

In bash, when setting a variable to a default value, if it has not already been set, it is typical to follow the pattern:

: ${MY_VAR=default}

However, this syntax does not work for an array. Bash 3.2 does not give an equivalent one line version of this. Instead, using set_array_default, an array can be set to a default value if not already set (albeit, in two lines).

It works by checking if an array is set. If it is set, nothing happens. If it is not set, it will copy the rest of the arguments (the default values) to the array named.

Note

An empty array counts as set

Example

set_array_default MY_ARRAY default1 default\ 2 "default  3"
pretty_print_help
Arguments:

stdin - Each line is an entry in the pretty printout, separated by ” ${JUST_HELP_SEPARATOR} ” (without the quotes, but with the spaces)

Parameters:

indent - How much the right side should be indented to make a uniform output

Restructures text to indent properly on wrap around

Each line consists of a command that will be printed on the left, and the indented description on the right. The description is wrapped around based on tput cols.

Prints the auto generated help info from Justfile

is_powershell

Check if the current command window is powershell

Using a Window’s title trick, determine if the shell is running in powershell or some other shell (e.g., Windows command prompt, cygwin or git bash)

need_tty

Check to see if a tty is missing. Normal tty checks do not work in mintty, as the pts appears to be a tty to native apps, but external apps will see a pipe. Checking to see if stdin has a name of “None” will tell us if we don’t have a piped stdin.

Calling this function is an expensive operation, and takes roughly 1-2 seconds (to call a new powershell). Setting JUST_IS_TTY to 1 will cause the function to return false instantly.

Parameters:

[JUST_IS_TTY] - If set to 1`, need_tty automatically returns 1. If set to 0, then need_tty will automatically returns 0 once.

If JUST_IS_TTY is set in a local.env file, then it should be set conditionally:

: ${JUST_IS_TTY=0}

This way it is triggered only once, instead of every time local.env is source, which can be quite frequently.

One use case for this is “ssh from linux into windows, start git bash, . setup.env, and then run python”. This will detect a fake tty name, because it is piped. However, you still need a tty because in python up and down will not work. I do not know why in this case…

setup_tty

Pops up a new powershell window and runs just

Cygwin bash is pretty bad. The new git bash (MINGW64) does not have a tty. This is a problem for docker. Powershell does have a tty, but cannot run bash scrips natively. The solution is to run bash in powershell (which is not as straight forward as it sounds). This function is designed to re-execute in a new powershell on Windows if not in powershell

Parameters:

[JUST_PTY] - PTY app to use create a psuedoterminal for windows apps. By default, uses winpty. Set to powershell for the old behavior

Usage

setup_tty ${@+”${@}”}

defaultify

Default commands for just

Handles a few default commands for just:

  • Calls plugins specified in JUST_DEFAULTIFY_FUNCTIONS

  • –dryrun|-n - Sets DRYRUN to print_command print_command. This way ${DRYRUN} can be put in front of any command and be printed instead of executed when in dryrun mode

  • –separator - Used to override the JUST_SEPARATOR (default –) to anything else. This only affect commands that use get_args

  • -h|–help|help - Prints out help using print_help

  • _null - A target that does nothing. This is seldom needed.

      • For all other commands not captured yet, called unknownify (which can be overridden for other behavior) to print an error message.

unknownify
Parameters:

JUST_FILE_NOT_FOUND - Prints out a different message if JUST_FILE_NOT_FOUND is set to 1

The function executed when an unknown target is specified

The default behavior is to print an error and exit 1. However, a custom unknownify can be declared in Justfile to override this behavior

extra_args

The number of additional arguments consumed in a caseify target

When writing a caseify target, by default one argument is consumed. This is enough for any simple target. However some targets need additional arguments.

There are really three situation when extra arguments are needed

  1. A fixed number of arguments. For example, if 3 arguments are needed, just use $1, $2, $3, and set extra_args=3

  2. The rest of the arguments are going to be consumed. In this case, use all the arguments (typically by $@) and set extra_args=${#}

  3. An unknown number of arguments need to be used, and maybe multiple groups of unknown arguments. This is the case where JUST_SEPARATOR is used. (See EXAMPLE)

Example

# Lets say we call:

just test 11 22 33 -- aa bb cc dd -- _null

# test is called with 3 arguments
# aa is called with 3 arguments
# _null is called

The deprecated way

# Lets say we call:

  just test -- 11 22 33 -- aa bb cc dd -- _null

  # And I have a target test that takes two sets of arguments of unknown length

test)
  get_args ${@+"${@}"}
  first=${args[@]+"${args[@]}"}
  get_additional_args ${@+"${@}"}
  second=${args[@]+"${args[@]}"}
  ;;

In this case, there is no need to add extra_args, get_args does this already

justify
Arguments:

$1... - list of targets

The main loop of just

Handles determining what subcommands are and calling commands and subcommands.

When one target is called from another target, justify should be used to do the calling, for example:

justify target2

callify

Helper for consuming arguments and calling a function with them

Takes: cmd – $1 $2 $3 … $n – $m $m+1 … and calls: cmd $1 $2 $3 … $n and consumes n+2 args Trailing – is optional

Example

target)
  callify python ${@+"${@}"}
  ;;

just target -- -c "print 1+3"

Note

Not sure this is worth keeping

get_args
Arguments:

Inputs $@ - All the unconsumed arguments

Output:

args - Array of unknown number of arguments consumed get_args_args_used - Number of arguments used, including separator

Get and consume an unknown collection of arguments

Gets an unknown number of arguments. The ending of the collection of arguments is annotated with the JUST_SEPARATOR. The trailing annotation is optional as long as there are no more just commands following

Bugs

This will conveniently update extra_args inside of the Justfile caseify function. However, if you are calling from another function (i.e., not writing a caseify section), this will produce incorrect behavior; therefore, extra_args should be made a local variable in the calling function

Note

get_args_args_used is a global variable. Unsetting it can cause unexpected behavior

get_additional_args

Get and consume additional collections of arguments

get_args can only be called once, but get_additional_args can be called continuously after the first call of get_args

Example

Must be called after get_args with all arguments passed in. For example:

 target)
   get_args ${@+"${@}"}
   args1=(${args[@]+"${args[@]}"})
   get_additional_args ${@+"${@}"}
   args2=(${args[@]+"${args[@]}"})
   get_additional_args ${@+"${@}"}
   args3=(${args[@]+"${args[@]}"})
   ;;

just target 11 22 33 -- aa bb cc -- '!!' '@@' '##'

#args1=(11 22 33)
#args2=(aa bb cc)
#args3=(!! @@ ##)
safe_load

A non-eval method for loading and exporting a text file of keys/values

Arguments:

Inputs $1 - Filename of file to be loaded

Parameters:

[JUST_SAFE_LOAD_DELIMITER] - By default, = is used between key and value. If = is needed, then this environment variable can override the delimiter.

Output:

All keys are set as environment variables and exported

Example

key1=value_one
key2=this is another value

Note

Does not support comments, blank lines, or anything else other than key=value

Bugs

As with anything in a language like bash, it’s not guaranteed that an arbitrary command won’t be executed with this, but as far as is known, there are no known issues with this function.

just_error

Helper function to be combined with calls to print a useful error message on error.

Errors captured by just_functions.bsh just_error will not print out an error stack.

Arguments:

Inputs $1... - Message to echo on error

Return Value:
  • Returns the same return value of the previously run command

Output:

Echos message

Example

run_some_command || just_error "That command failed, here's some helpful advise"
.justplugins

Plugin file

The filename defaults to .justplugins and sits next to your Justfile, but can be overridden by exporting the environment variable JUST_PLUGIN_FILE.

Lists the various plugin files. Blank lines and # comment lines are allowed