Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions go-template
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
# Make sure the variables within this script are configured as necessary for
# your program. You can add any other initialization or configuration between:
#
# . "$_GO_SCRIPT_BASH_CORE_DIR/go-core.bash" "$GO_SCRIPTS_DIR"`
# . "$GO_SCRIPT_BASH_CORE_DIR/go-core.bash" "$GO_SCRIPTS_DIR"`
# `@go "$@"`

# Set to 'true' if your script is a standalone program, i.e. not bound to
Expand Down Expand Up @@ -50,7 +50,6 @@ declare GO_SCRIPT_BASH_DOWNLOAD_URL="${GO_SCRIPT_BASH_DOWNLOAD_URL:-${GO_SCRIPT_
download_go_script_bash_tarball() {
# GitHub removes the leading 'v' from the archive's output directory.
local unpacked_dir="go-script-bash-${GO_SCRIPT_BASH_VERSION#v}"
local unpacked_core="$unpacked_dir/go-core.bash"
local core_dir_parent="${GO_SCRIPT_BASH_CORE_DIR%/*}"
local url="$GO_SCRIPT_BASH_DOWNLOAD_URL"
local protocol="${url%%://*}"
Expand Down Expand Up @@ -84,7 +83,8 @@ download_go_script_bash_tarball() {
fi
printf "Downloading framework from '%s'...\n" "$url"

if ! tar -xzf - < <("${download_cmd[@]}") || [[ ! -f "$unpacked_core" ]]; then
if ! "${download_cmd[@]}" | tar -xzf - ||
[[ "${PIPESTATUS[0]}" -ne '0' ]]; then
printf "Failed to download from '%s'.\n" "$url" >&2
return 1
elif [[ ! -d "$core_dir_parent" ]] && ! mkdir -p "$core_dir_parent" ; then
Expand Down
104 changes: 104 additions & 0 deletions lib/archive
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#! /usr/bin/env bash
#
# Archive file utilities
#
# Exports:
# @go.create_gzipped_tarball
# Creates a Gzipped Tar archive file (.tar.gz)

. "$_GO_USE_MODULES" 'fileutil' 'log' 'path'

# Creates a Gzipped Tar archive file (.tar.gz)
#
# By default, will create a tarball with the same basename as that of the source
# directory plus '.tar.gz', e.g. a source directory of 'foo' will create
# 'foo.tar.gz'. The resulting tarball will extract to a directory with that
# basename.
#
# If `--name` is specified, a new directory of that name will be created as a
# sibling of the source directory (if the directory or symlink doesn't yet
# exist), the selected contents from the source directory will be mirrored into
# it, and the tarball will be created from that sibling.This means the resulting
# tarball's name will be based on `--name`, and will extract to the directory
# specified by `--name`. This sibling directory will be deleted automatically
# unless `--keep-mirror` is specified.
#
# Using a mirror instead of a symlink is portable on platforms without symlink
# capability. However, this function correctly handles `source_dir` and tarball
# `--name` symlinks.
#
# If no specific items are listed after the source directory, the entire
# directory will be archived. These items should be relative paths within the
# source directory.
#
# Options:
# --name: Specifies an alternative name for the tarball
# --keep-mirror: Keep the new directory created when `--name` is specified
# --remove-source: Remove the source directory after the tarball is created
#
# Arguments:
# source_dir: Directory containing files to archive
# ...: If specified, selected items from `source_dir` to archive
@go.create_gzipped_tarball() {
local source_dir
local tarball_dir
local real_source_dir
local real_tarball_dir
local tarball
local items
local keep_mirror
local remove_source
local varname

while [[ "$#" -ne '0' ]]; do
case "$1" in
--name)
tarball_dir="$2"
shift 2
;;
--keep-mirror|--remove-source)
varname="${1#--}"
printf -v "${varname//-/_}" 'true'
shift
;;
*)
break
;;
esac
done

@go.canonicalize_path --pwd 'source_dir' "$1"
shift

if [[ -n "$tarball_dir" ]]; then
tarball_dir="${source_dir%/*}/${tarball_dir}"
else
tarball_dir="$source_dir"
fi
tarball="${tarball_dir}.tar.gz"

@go.realpath 'real_source_dir' "$source_dir"
@go.realpath 'real_tarball_dir' "$tarball_dir"

if [[ ! -d "$source_dir" ]]; then
@go.log FATAL "Source directory $source_dir doesn't exist"
elif [[ "$real_source_dir" != "$real_tarball_dir" ]]; then
@go.mirror_directory "$source_dir" "$tarball_dir" "$@"
else
keep_mirror='true'
fi

if [[ "$#" -eq '0' ]]; then
items=("${tarball_dir##*/}/.")
else
items=("${@/#/${tarball_dir##*/}/}")
fi

if ! tar -czf "$tarball" -C "${real_tarball_dir%/*}" "${items[@]}"; then
@go.log FATAL "Failed to create $tarball from $source_dir"
elif [[ -z "$keep_mirror" ]] && ! rm -rf "$tarball_dir"; then
@go.log FATAL "Failed to remove $tarball_dir after creating $tarball"
elif [[ -n "$remove_source" ]] && ! rm -rf "$source_dir"; then
@go.log FATAL "Failed to remove $source_dir after creating $tarball"
fi
}
26 changes: 17 additions & 9 deletions lib/fileutil
Original file line number Diff line number Diff line change
Expand Up @@ -165,23 +165,35 @@
# directory exists. Automatically creates the destination directory if it
# doesn't exist.
#
# If specific path arguments aren't given after the `src_dir` and `dest_dir`
# arguments, all of the items in `src_dir` will be included by default. If they
# are given, only those items will be mirrored.
#
# Uses only `tar` features that are portable across platform variants. More
# portable than `rsync`, which isn't installed by default on some systems; and
# can be faster than `cp -a`.
#
# Arguments:
# src_dir: Original directory path
# dest_dir: Mirrored directory path
# ...: Paths relative to `src_dir` to include in the mirror
# ...: Specific paths relative to `src_dir` to include in the mirror
@go.mirror_directory() {
local src_dir="$1"
local dest_dir="$2"
local items=("${@:3}")
local real_src
local real_dest

@go.canonicalize_path --pwd 'src_dir' "$1"
@go.canonicalize_path --pwd 'dest_dir' "$2"

@go.realpath 'real_src' "$src_dir"
@go.realpath 'real_dest' "$dest_dir"

if [[ "${#items[@]}" -eq '0' ]]; then
items=('.')
fi

if [[ "$real_src" == "$real_dest" ]]; then
@go.log FATAL "Real source and destination dirs are the same:"$'\n'\
" source: $src_dir"$'\n'\
Expand All @@ -191,7 +203,7 @@
@go.log FATAL "Source directory $src_dir doesn't exist"
elif [[ ! -d "$dest_dir" ]] && ! mkdir -p "$dest_dir"; then
@go.log FATAL "Failed to create destination directory $dest_dir"
elif ! tar -cf - -C "$src_dir" "${@:3}" | tar -xf - -C "$dest_dir" ||
elif ! tar -cf - -C "$src_dir" "${items[@]}" | tar -xf - -C "$dest_dir" ||
[[ "${PIPESTATUS[0]}" != '0' ]]; then
@go.log FATAL "Failed to mirror files from $src_dir to $dest_dir"
fi
Expand Down Expand Up @@ -245,8 +257,7 @@ _@go.parse_copy_files_safely_args() {
while [[ "$#" -ne '0' ]]; do
case "$1" in
--src-dir)
@go.add_parent_dir_if_relative_path '__go_src_dir' "$2"
@go.canonicalize_path '__go_src_dir' "$__go_src_dir"
@go.canonicalize_path --pwd '__go_src_dir' "$2"
shift 2
;;
--dir-mode)
Expand All @@ -268,8 +279,7 @@ _@go.parse_copy_files_safely_args() {
*)
__go_src_files=("${@:1:$(($# - 1))}")
__go_dest_dir="${!#}"
@go.add_parent_dir_if_relative_path '__go_dest_dir' "$__go_dest_dir"
@go.canonicalize_path '__go_dest_dir' "$__go_dest_dir"
@go.canonicalize_path --pwd '__go_dest_dir' "$__go_dest_dir"
break
;;
esac
Expand Down Expand Up @@ -310,9 +320,7 @@ _@go.set_source_files_for_copy_files_safely() {
__go_src_files=()

for orig_src in "$@"; do
@go.add_parent_dir_if_relative_path --parent "$__go_src_dir" \
'absolute_src' "$orig_src"
@go.canonicalize_path 'absolute_src' "$absolute_src"
@go.canonicalize_path --parent "$__go_src_dir" 'absolute_src' "$orig_src"
canonical_src="${absolute_src#$__go_src_dir/}"

if [[ -z "$orig_src" ]]; then
Expand Down
21 changes: 21 additions & 0 deletions lib/path
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,35 @@
# This will reduce any consecutive string of slashes to a single slash, and trim
# a trailing slash if one remains.
#
# Options:
# --pwd: Prepend `$PWD` to path before canonicalization if relative
# --parent <dir>: Specifies parent dir prepended before canonicalization
#
# Arguments:
# result_var_name: Name of the variable into which the result will be stored
# path: Path to canonicalize
@go.canonicalize_path() {
local add_pwd
local add_parent=()

case "$1" in
--pwd)
add_pwd='true'
shift
;;
--parent)
add_parent=('--parent' "$2")
shift 2
;;
esac
@go.validate_identifier_or_die 'Canonicalized path result variable' "$1"

printf -v "$1" '%s' "${2}${2:+/}"

if [[ -n "${!1}" && (-n "$add_pwd" || "${#add_parent[@]}" -ne '0') ]]; then
@go.add_parent_dir_if_relative_path "${add_parent[@]}" "$1" "${!1}"
fi

while [[ "${!1}" =~ //+ ]]; do
printf -v "$1" '%s' "${!1/"${BASH_REMATCH[0]}"//}"
done
Expand Down
Loading