<commit_before>
# Show a prompt for a command
function plugin_prompt() {
  if [[ -z "${HIDE_PROMPT:-}" ]] ; then
    echo -ne "\033[90m$\033[0m" >&2
    printf " %q" "$@" >&2
    echo >&2
  fi
}

# Shows the command being run, and runs it
function plugin_prompt_and_run() {
  plugin_prompt "$@"
  "$@"
}

# Shows the command about to be run, and exits if it fails
function plugin_prompt_and_must_run() {
  plugin_prompt_and_run "$@" || exit $?
}

# Shorthand for reading env config
function plugin_read_config() {
  local var="BUILDKITE_PLUGIN_DOCKER_COMPOSE_${1}"
  local default="${2:-}"
  echo "${!var:-$default}"
}

# Read agent metadata for pre-built images, returns empty string on error
function plugin_get_build_image_metadata() {
  local service="$1"
  local key="docker-compose-plugin-built-image-tag-${service}"
  plugin_prompt buildkite-agent meta-data get "$key"
  buildkite-agent meta-data get "$key" 2>/dev/null || true
}

# Write agent metadata for pre-built images, exits on error
function plugin_set_build_image_metadata() {
  local service="$1"
  local value="$2"
  plugin_prompt_and_must_run buildkite-agent meta-data set \
    "docker-compose-plugin-built-image-tag-${service}" "$value"
}

# Returns the name of the docker compose project for this build
function docker_compose_project_name() {
  # No dashes or underscores because docker-compose will remove them anyways
  echo "buildkite${BUILDKITE_JOB_ID//-}"
}

# Returns the first docker compose config file name
function docker_compose_config_files() {
  if [[ -n "${BUILDKITE_PLUGIN_DOCKER_COMPOSE_CONFIG_0:-}" ]]; then
    # Plugin config specified an array of config files
    local i=0
    local parameter="BUILDKITE_PLUGIN_DOCKER_COMPOSE_CONFIG_${i}"
    while [[ -n "${!parameter:-}" ]]; do
      echo "${!parameter}"
      i=$((i+1))
      parameter="BUILDKITE_PLUGIN_DOCKER_COMPOSE_CONFIG_${i}"
    done
  elif [[ -n "${BUILDKITE_PLUGIN_DOCKER_COMPOSE_CONFIG:-}" ]]; then
    # Plugin config may be colon-separated files
    declare file
    declare -a files
    IFS=":" read -ra files <<< "$BUILDKITE_PLUGIN_DOCKER_COMPOSE_CONFIG"
    for file in "${files[@]}"; do
      echo "$file"
    done
  else
    # Use default docker compose location
    echo "docker-compose.yml"
  fi
}

# Returns the first docker compose config file name
function docker_compose_config_file() {
  docker_compose_config_files | head -n1
}

# Returns the version of the first docker compose config file
function docker_compose_config_version() {
  sed -n "s/version: ['\"]\(.*\)['\"]/\1/p" < "$(docker_compose_config_file)"
}

# Build an docker-compose file that overrides the image for a given service<commit_msg>Implement a generic plugin_read_list<commit_after>
# Show a prompt for a command
function plugin_prompt() {
  if [[ -z "${HIDE_PROMPT:-}" ]] ; then
    echo -ne "\033[90m$\033[0m" >&2
    printf " %q" "$@" >&2
    echo >&2
  fi
}

# Shows the command being run, and runs it
function plugin_prompt_and_run() {
  plugin_prompt "$@"
  "$@"
}

# Shows the command about to be run, and exits if it fails
function plugin_prompt_and_must_run() {
  plugin_prompt_and_run "$@" || exit $?
}

# Shorthand for reading env config
function plugin_read_config() {
  local var="BUILDKITE_PLUGIN_DOCKER_COMPOSE_${1}"
  local default="${2:-}"
  echo "${!var:-$default}"
}

# Read agent metadata for pre-built images, returns empty string on error
function plugin_get_build_image_metadata() {
  local service="$1"
  local key="docker-compose-plugin-built-image-tag-${service}"
  plugin_prompt buildkite-agent meta-data get "$key"
  buildkite-agent meta-data get "$key" 2>/dev/null || true
}

# Write agent metadata for pre-built images, exits on error
function plugin_set_build_image_metadata() {
  local service="$1"
  local value="$2"
  plugin_prompt_and_must_run buildkite-agent meta-data set \
    "docker-compose-plugin-built-image-tag-${service}" "$value"
}

# Reads either a value or a list from plugin config
function plugin_read_list() {
  local prefix="BUILDKITE_PLUGIN_DOCKER_COMPOSE_$1"
  local parameter="${prefix}_0"

  if [[ -n "${!parameter:-}" ]]; then
    local i=0
    local parameter="${prefix}_${i}"
    while [[ -n "${!parameter:-}" ]]; do
      echo "${!parameter}"
      i=$((i+1))
      parameter="${prefix}_${i}"
    done
  elif [[ -n "${!prefix:-}" ]]; then
    echo "${!prefix}"
  else
    return 1
  fi
}

# Returns the name of the docker compose project for this build
function docker_compose_project_name() {
  # No dashes or underscores because docker-compose will remove them anyways
  echo "buildkite${BUILDKITE_JOB_ID//-}"
}

# Returns the name of the docker compose container that corresponds to the
# given service
function docker_compose_container_name() {
  echo "$(docker_compose_project_name)_$1"
}

# Returns all docker compose config file names split by newlines
function docker_compose_config_files() {
  if ! config_files=( $( plugin_read_list CONFIG ) ) ; then
    echo "docker-compose.yml"
  fi

  # Process any (deprecated) colon delimited config paths
  for value in "${config_files[@]}" ; do
    echo "$value" | tr ':' '\n'
  done
}

# Returns the first docker compose config file name
function docker_compose_config_file() {
  if ! config_files=( $(docker_compose_config_files) ) ; then
    echo "docker-compose.yml"
  fi

  echo "${config_files[0]}"
}

# Returns the version of the first docker compose config file
function docker_compose_config_version() {
  sed -n "s/version: ['\"]\(.*\)['\"]/\1/p" < "$(docker_compose_config_file)"
}

# Build an docker-compose file that overrides the image for a given service
{'fraction_non_alphanumeric': 0.128068303094984, 'fraction_numerical': 0.008715759516186411, 'mean_word_length': 4.235567970204841, 'pattern_counts': {'":': 1, '<': 8, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5474336', 'n_tokens_mistral': 1945, 'n_tokens_neox': 1835, 'n_words': 536}