Skip to content

Commit 98bb9ba

Browse files
authored
Merge pull request #211 from mbland/tarball-#186
Add @go.create_gzipped_tarball and perform other small refactors
2 parents 2f731d6 + e885b4a commit 98bb9ba

File tree

8 files changed

+550
-97
lines changed

8 files changed

+550
-97
lines changed

go-template

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
# Make sure the variables within this script are configured as necessary for
2020
# your program. You can add any other initialization or configuration between:
2121
#
22-
# . "$_GO_SCRIPT_BASH_CORE_DIR/go-core.bash" "$GO_SCRIPTS_DIR"`
22+
# . "$GO_SCRIPT_BASH_CORE_DIR/go-core.bash" "$GO_SCRIPTS_DIR"`
2323
# `@go "$@"`
2424

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

87-
if ! tar -xzf - < <("${download_cmd[@]}") || [[ ! -f "$unpacked_core" ]]; then
86+
if ! "${download_cmd[@]}" | tar -xzf - ||
87+
[[ "${PIPESTATUS[0]}" -ne '0' ]]; then
8888
printf "Failed to download from '%s'.\n" "$url" >&2
8989
return 1
9090
elif [[ ! -d "$core_dir_parent" ]] && ! mkdir -p "$core_dir_parent" ; then

lib/archive

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#! /usr/bin/env bash
2+
#
3+
# Archive file utilities
4+
#
5+
# Exports:
6+
# @go.create_gzipped_tarball
7+
# Creates a Gzipped Tar archive file (.tar.gz)
8+
9+
. "$_GO_USE_MODULES" 'fileutil' 'log' 'path'
10+
11+
# Creates a Gzipped Tar archive file (.tar.gz)
12+
#
13+
# By default, will create a tarball with the same basename as that of the source
14+
# directory plus '.tar.gz', e.g. a source directory of 'foo' will create
15+
# 'foo.tar.gz'. The resulting tarball will extract to a directory with that
16+
# basename.
17+
#
18+
# If `--name` is specified, a new directory of that name will be created as a
19+
# sibling of the source directory (if the directory or symlink doesn't yet
20+
# exist), the selected contents from the source directory will be mirrored into
21+
# it, and the tarball will be created from that sibling.This means the resulting
22+
# tarball's name will be based on `--name`, and will extract to the directory
23+
# specified by `--name`. This sibling directory will be deleted automatically
24+
# unless `--keep-mirror` is specified.
25+
#
26+
# Using a mirror instead of a symlink is portable on platforms without symlink
27+
# capability. However, this function correctly handles `source_dir` and tarball
28+
# `--name` symlinks.
29+
#
30+
# If no specific items are listed after the source directory, the entire
31+
# directory will be archived. These items should be relative paths within the
32+
# source directory.
33+
#
34+
# Options:
35+
# --name: Specifies an alternative name for the tarball
36+
# --keep-mirror: Keep the new directory created when `--name` is specified
37+
# --remove-source: Remove the source directory after the tarball is created
38+
#
39+
# Arguments:
40+
# source_dir: Directory containing files to archive
41+
# ...: If specified, selected items from `source_dir` to archive
42+
@go.create_gzipped_tarball() {
43+
local source_dir
44+
local tarball_dir
45+
local real_source_dir
46+
local real_tarball_dir
47+
local tarball
48+
local items
49+
local keep_mirror
50+
local remove_source
51+
local varname
52+
53+
while [[ "$#" -ne '0' ]]; do
54+
case "$1" in
55+
--name)
56+
tarball_dir="$2"
57+
shift 2
58+
;;
59+
--keep-mirror|--remove-source)
60+
varname="${1#--}"
61+
printf -v "${varname//-/_}" 'true'
62+
shift
63+
;;
64+
*)
65+
break
66+
;;
67+
esac
68+
done
69+
70+
@go.canonicalize_path --pwd 'source_dir' "$1"
71+
shift
72+
73+
if [[ -n "$tarball_dir" ]]; then
74+
tarball_dir="${source_dir%/*}/${tarball_dir}"
75+
else
76+
tarball_dir="$source_dir"
77+
fi
78+
tarball="${tarball_dir}.tar.gz"
79+
80+
@go.realpath 'real_source_dir' "$source_dir"
81+
@go.realpath 'real_tarball_dir' "$tarball_dir"
82+
83+
if [[ ! -d "$source_dir" ]]; then
84+
@go.log FATAL "Source directory $source_dir doesn't exist"
85+
elif [[ "$real_source_dir" != "$real_tarball_dir" ]]; then
86+
@go.mirror_directory "$source_dir" "$tarball_dir" "$@"
87+
else
88+
keep_mirror='true'
89+
fi
90+
91+
if [[ "$#" -eq '0' ]]; then
92+
items=("${tarball_dir##*/}/.")
93+
else
94+
items=("${@/#/${tarball_dir##*/}/}")
95+
fi
96+
97+
if ! tar -czf "$tarball" -C "${real_tarball_dir%/*}" "${items[@]}"; then
98+
@go.log FATAL "Failed to create $tarball from $source_dir"
99+
elif [[ -z "$keep_mirror" ]] && ! rm -rf "$tarball_dir"; then
100+
@go.log FATAL "Failed to remove $tarball_dir after creating $tarball"
101+
elif [[ -n "$remove_source" ]] && ! rm -rf "$source_dir"; then
102+
@go.log FATAL "Failed to remove $source_dir after creating $tarball"
103+
fi
104+
}

lib/fileutil

+17-9
Original file line numberDiff line numberDiff line change
@@ -165,23 +165,35 @@
165165
# directory exists. Automatically creates the destination directory if it
166166
# doesn't exist.
167167
#
168+
# If specific path arguments aren't given after the `src_dir` and `dest_dir`
169+
# arguments, all of the items in `src_dir` will be included by default. If they
170+
# are given, only those items will be mirrored.
171+
#
168172
# Uses only `tar` features that are portable across platform variants. More
169173
# portable than `rsync`, which isn't installed by default on some systems; and
170174
# can be faster than `cp -a`.
171175
#
172176
# Arguments:
173177
# src_dir: Original directory path
174178
# dest_dir: Mirrored directory path
175-
# ...: Paths relative to `src_dir` to include in the mirror
179+
# ...: Specific paths relative to `src_dir` to include in the mirror
176180
@go.mirror_directory() {
177181
local src_dir="$1"
178182
local dest_dir="$2"
183+
local items=("${@:3}")
179184
local real_src
180185
local real_dest
181186

187+
@go.canonicalize_path --pwd 'src_dir' "$1"
188+
@go.canonicalize_path --pwd 'dest_dir' "$2"
189+
182190
@go.realpath 'real_src' "$src_dir"
183191
@go.realpath 'real_dest' "$dest_dir"
184192

193+
if [[ "${#items[@]}" -eq '0' ]]; then
194+
items=('.')
195+
fi
196+
185197
if [[ "$real_src" == "$real_dest" ]]; then
186198
@go.log FATAL "Real source and destination dirs are the same:"$'\n'\
187199
" source: $src_dir"$'\n'\
@@ -191,7 +203,7 @@
191203
@go.log FATAL "Source directory $src_dir doesn't exist"
192204
elif [[ ! -d "$dest_dir" ]] && ! mkdir -p "$dest_dir"; then
193205
@go.log FATAL "Failed to create destination directory $dest_dir"
194-
elif ! tar -cf - -C "$src_dir" "${@:3}" | tar -xf - -C "$dest_dir" ||
206+
elif ! tar -cf - -C "$src_dir" "${items[@]}" | tar -xf - -C "$dest_dir" ||
195207
[[ "${PIPESTATUS[0]}" != '0' ]]; then
196208
@go.log FATAL "Failed to mirror files from $src_dir to $dest_dir"
197209
fi
@@ -245,8 +257,7 @@ _@go.parse_copy_files_safely_args() {
245257
while [[ "$#" -ne '0' ]]; do
246258
case "$1" in
247259
--src-dir)
248-
@go.add_parent_dir_if_relative_path '__go_src_dir' "$2"
249-
@go.canonicalize_path '__go_src_dir' "$__go_src_dir"
260+
@go.canonicalize_path --pwd '__go_src_dir' "$2"
250261
shift 2
251262
;;
252263
--dir-mode)
@@ -268,8 +279,7 @@ _@go.parse_copy_files_safely_args() {
268279
*)
269280
__go_src_files=("${@:1:$(($# - 1))}")
270281
__go_dest_dir="${!#}"
271-
@go.add_parent_dir_if_relative_path '__go_dest_dir' "$__go_dest_dir"
272-
@go.canonicalize_path '__go_dest_dir' "$__go_dest_dir"
282+
@go.canonicalize_path --pwd '__go_dest_dir' "$__go_dest_dir"
273283
break
274284
;;
275285
esac
@@ -310,9 +320,7 @@ _@go.set_source_files_for_copy_files_safely() {
310320
__go_src_files=()
311321

312322
for orig_src in "$@"; do
313-
@go.add_parent_dir_if_relative_path --parent "$__go_src_dir" \
314-
'absolute_src' "$orig_src"
315-
@go.canonicalize_path 'absolute_src' "$absolute_src"
323+
@go.canonicalize_path --parent "$__go_src_dir" 'absolute_src' "$orig_src"
316324
canonical_src="${absolute_src#$__go_src_dir/}"
317325

318326
if [[ -z "$orig_src" ]]; then

lib/path

+21
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,35 @@
2525
# This will reduce any consecutive string of slashes to a single slash, and trim
2626
# a trailing slash if one remains.
2727
#
28+
# Options:
29+
# --pwd: Prepend `$PWD` to path before canonicalization if relative
30+
# --parent <dir>: Specifies parent dir prepended before canonicalization
31+
#
2832
# Arguments:
2933
# result_var_name: Name of the variable into which the result will be stored
3034
# path: Path to canonicalize
3135
@go.canonicalize_path() {
36+
local add_pwd
37+
local add_parent=()
38+
39+
case "$1" in
40+
--pwd)
41+
add_pwd='true'
42+
shift
43+
;;
44+
--parent)
45+
add_parent=('--parent' "$2")
46+
shift 2
47+
;;
48+
esac
3249
@go.validate_identifier_or_die 'Canonicalized path result variable' "$1"
3350

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

53+
if [[ -n "${!1}" && (-n "$add_pwd" || "${#add_parent[@]}" -ne '0') ]]; then
54+
@go.add_parent_dir_if_relative_path "${add_parent[@]}" "$1" "${!1}"
55+
fi
56+
3657
while [[ "${!1}" =~ //+ ]]; do
3758
printf -v "$1" '%s' "${!1/"${BASH_REMATCH[0]}"//}"
3859
done

0 commit comments

Comments
 (0)