aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bpkg-util/manage.in183
1 files changed, 82 insertions, 101 deletions
diff --git a/bpkg-util/manage.in b/bpkg-util/manage.in
index 1151ef8..8ff51e9 100644
--- a/bpkg-util/manage.in
+++ b/bpkg-util/manage.in
@@ -122,25 +122,6 @@ trap "{ cd '$owd'; exit 1; }" ERR
set -o errtrace # Trap in functions and subshells.
set -o pipefail # Fail if any pipeline command fails.
shopt -s lastpipe # Execute last pipeline command in the current shell.
-
-# @@ With nullglob enabled I had to make many instances of the following
-# replacements:
-#
-# unset a[$i]
-# =>
-# unset "a[$i]"
-#
-# [ -v a[$i] ]
-# =>
-# [ -v "a[$i]" ]
-#
-# Required because the [] make these things look like globs/patterns which
-# bash then replaces with "" if nullglob is turned on. This is not an issue
-# with [[, however. So `[[ -v a[$i] ]]` works without quotes (while at
-# the moment we still quote it for the consistency with [...]).
-#
-# In this light, should we consider always using [[ instead of [?
-#
shopt -s nullglob # Expand no-match globs to nothing rather than themselves.
@import bpkg-util/utility@
@@ -150,7 +131,7 @@ shopt -s nullglob # Expand no-match globs to nothing rather than themselves.
#
bpkg_util_bpkg="$(dirname "$(realpath "${BASH_SOURCE[0]}")")/bpkg"
-if [ ! -x "$bpkg_util_bpkg" ]; then
+if [[ ! -x "$bpkg_util_bpkg" ]]; then
bpkg_util_bpkg=bpkg
fi
@@ -167,7 +148,7 @@ mode="source"
#
filter="*"
-while [ "$#" -gt 0 ]; do
+while [[ "$#" -gt 0 ]]; do
case "$1" in
--testing=*)
filter="${1#--testing=}"
@@ -212,9 +193,9 @@ done
# Set the working directory.
#
-if [ $# -eq 0 ]; then
+if [[ "$#" -eq 0 ]]; then
dir="$owd"
-elif [ $# -eq 1 ]; then
+elif [[ "$#" -eq 1 ]]; then
dir="${1%/}" # <dir> with trailing slash removed.
else
error "$usage"
@@ -226,7 +207,7 @@ fi
# destination-management mode.
#
real_src_dir="$dir/$src_repo_name" # The real source repository directory.
-if [ "$mode" != "source" ]; then
+if [[ "$mode" != "source" ]]; then
src_repo_name="$dst_repo_name"
fi
@@ -239,21 +220,21 @@ fi
src_dir="$dir/$src_repo_name"
dst_dir="$dir/$dst_repo_name"
-if [ ! -d "$src_dir" ]; then
+if [[ ! -d "$src_dir" ]]; then
error "'$src_dir' does not exist or is not a directory"
fi
-if [ ! -d "$dst_dir" ]; then
+if [[ ! -d "$dst_dir" ]]; then
error "'$dst_dir' does not exist or is not a directory"
fi
# Check that both git repositories are clean.
#
-if [ -n "$(git -C $src_dir status --porcelain)" ]; then
+if [[ -n "$(git -C $src_dir status --porcelain)" ]]; then
error "git repository in '$src_dir' is not clean"
fi
-if [ -n "$(git -C $dst_dir status --porcelain)" ]; then
+if [[ -n "$(git -C $dst_dir status --porcelain)" ]]; then
error "git repository in '$dst_dir' is not clean"
fi
@@ -367,7 +348,7 @@ function init_globals ()
local s
for s in "${src_sections[@]}"; do
local d="$src_dir/$s"
- if [ -d "$d" ]; then
+ if [[ -d "$d" ]]; then
local f
while read f; do
src_files+=("${f#$src_dir/}")
@@ -444,7 +425,7 @@ function init_globals ()
# If this is a pending commit, prepend its hash to the ordered array.
#
- if [ "${pending_set[$h]}" ]; then
+ if [[ "${pending_set[$h]}" ]]; then
pending_seq=("$h" "${pending_seq[@]}")
((++i))
fi
@@ -462,7 +443,7 @@ function cleanup ()
{
info "migration failed; resetting and cleaning repositories"
- if ([ "$mode" == "source" ] && ! run git -C "$src_dir" reset --hard) ||
+ if ([[ "$mode" == "source" ]] && ! run git -C "$src_dir" reset --hard) ||
! run git -C "$dst_dir" reset --hard ||
! run git -C "$dst_dir" clean --force; then
info "failed to reset/clean repositories -- manual intervention required"
@@ -560,14 +541,14 @@ function extract_pkg_info () # <archive>
local r
r=($(bpkg_util_pkg_verify_archive "$arc")) # <name> <version> <project>
- if [ ! -v "r[2]" ]; then
+ if [[ ! -v r[2] ]]; then
r[2]="${r[0]}"
fi
# Verify that the archive parent directory name matches the project.
#
local p="${r[2]}"
- if [ "$p" != "$(basename "$(dirname "$arc")")" ]; then
+ if [[ "$p" != "$(basename "$(dirname "$arc")")" ]]; then
error "'$arc' archive directory name does not match package project '$p'"
fi
@@ -601,12 +582,12 @@ function check_pkg_duplicate () # <pkg-name> <pkg-version>
IFS=$'\n' eval \
'p=($(bpkg_util_pkg_find_archive "$name-$version.*" "$dst_dir/$sd"))'
- if [ "${#p[@]}" -ne 0 ]; then
+ if [[ "${#p[@]}" -ne 0 ]]; then
local a="${p[0]}"
local n="${p[1]}"
local v="${p[2]}"
- if [ "$n" == "$name" ]; then
+ if [[ "$n" == "$name" ]]; then
error "duplicate of $name/$version at '$a'"
else
error "conflict of $name/$version with $n/$v at '$a'"
@@ -682,7 +663,7 @@ function remove_pkg_archives ()
#
local src="$sver"
local dst="$name/$dver"
- if [ "$dproj" != "$sproj" ]; then
+ if [[ "$dproj" != "$sproj" ]]; then
src+=" ($sproj)"
dst+=" ($dproj)"
fi
@@ -749,7 +730,7 @@ function collect_bundle_files ()
#
local fi
src_path_info "$f" | readarray -t fi
- if [ "${fi[0]}" == "unmanaged" ]; then
+ if [[ "${fi[0]}" == "unmanaged" ]]; then
info "cannot include commit $i: '$f' is unmanaged"
bundle_files=()
return
@@ -757,7 +738,7 @@ function collect_bundle_files ()
# Add this file only if it belongs to the current commit.
#
- if [ "${file_commits[$f]}" == "$h" ]; then
+ if [[ "${file_commits[$f]}" == "$h" ]]; then
bundle_files+=("$f")
fi
done < <(commit_files "$h")
@@ -774,7 +755,7 @@ function contains () # <target> <word0> <word1> ...
local w
for w in "$@"; do
- if [ "$w" == "$k" ]; then
+ if [[ "$w" == "$k" ]]; then
echo -n "true"
return
fi
@@ -935,10 +916,10 @@ function migrate_src ()
local ftype="${fi[0]}" # Current file's type.
local fproj="${fi[1]}" # Current file's project.
- if [ "$ftype" == "ownership" ]; then
+ if [[ "$ftype" == "ownership" ]]; then
owns+=("$f")
- elif [ "$ftype" == "archive" ]; then
+ elif [[ "$ftype" == "archive" ]]; then
pkgs+=("$f")
local fsect_dir="${fi[2]}" # Section dir from file path.
@@ -948,9 +929,9 @@ function migrate_src ()
# Set the source section name if unset; otherwise fail if the current
# file is not from the source section.
#
- if [ -z "$src_sect" ]; then
+ if [[ -z "$src_sect" ]]; then
src_sect="$fsect"
- elif [ "$fsect" != "$src_sect" ]; then
+ elif [[ "$fsect" != "$src_sect" ]]; then
info "'$f' is not in section $src_sect"
return
fi
@@ -959,9 +940,9 @@ function migrate_src ()
# Set the bundle project if unset; otherwise fail if the current file is
# not from the bundle project.
#
- if [ -z "$proj" ]; then
+ if [[ -z "$proj" ]]; then
proj="$fproj"
- elif [ "$fproj" != "$proj" ]; then
+ elif [[ "$fproj" != "$proj" ]]; then
info "'$f' is not in project $proj"
return
fi
@@ -978,18 +959,18 @@ function migrate_src ()
local src_cmsg # Source commit message.
local dst_cmsg # Destination commit message.
- if [ "${#pkgs[@]}" -ne 0 ]; then # Bundle contains package archive(s).
+ if [[ "${#pkgs[@]}" -ne 0 ]]; then # Bundle contains package archive(s).
dst_sect="$src_sect"
# If it exists, 'testing' overrides 'stable' at the destination.
#
- if [[ ("$dst_sect" == "stable") && -v "dst_sections[testing]" ]]; then
+ if [[ ("$dst_sect" == "stable") && -v dst_sections["testing"] ]]; then
dst_sect="testing"
fi
# Fail if the target section does not exist in the destination repository.
#
- if [ ! -v "dst_sections[$dst_sect]" ]; then
+ if [[ ! -v "dst_sections[$dst_sect]" ]]; then
info "section '$dst_sect' does not exist in the destination repository"
return
fi
@@ -1004,7 +985,7 @@ function migrate_src ()
# destination but enabled on source is probably obscure, but let's
# consider it possible since the submit-git handler allows such a setup.
#
- if [ -n "$dst_owners" ]; then
+ if [[ -n "$dst_owners" ]]; then
src_cmsg="Migrate $proj ownership info to $dst_repo_name"$'\n\n'
dst_cmsg="Migrate $proj ownership info from $src_repo_name"$'\n\n'
else
@@ -1077,7 +1058,7 @@ function migrate_src ()
# Update the commit messages and migrate the current package.
#
src_cmsg+=" remove $name/$version"$'\n'
- if [ "${#rv[@]}" -eq 0 ]; then
+ if [[ "${#rv[@]}" -eq 0 ]]; then
dst_cmsg+=" add $name/$version"$'\n'
else
local v
@@ -1101,11 +1082,11 @@ function migrate_src ()
for f in "${owns[@]}"; do
src_cmsg+=" remove $f"$'\n'
- if [ -n "$dst_owners" ]; then
+ if [[ -n "$dst_owners" ]]; then
local dp=$(dirname "${f/$src_owners/$dst_owners}") # Destination path.
local fn=$(basename "$f") # File name.
- if [ -f "$dst_dir/$dp/$fn" ]; then
+ if [[ -f "$dst_dir/$dp/$fn" ]]; then
error "$f already exists at $dst_dir/$dp/$fn"
fi
@@ -1121,7 +1102,7 @@ function migrate_src ()
info
run git -C "$src_dir" commit -m "$src_cmsg"
- if [ -n "$dst_cmsg" ]; then
+ if [[ -n "$dst_cmsg" ]]; then
info
run git -C "$dst_dir" commit -m "$dst_cmsg"
fi
@@ -1206,7 +1187,7 @@ function migrate_dst ()
# Fail if the source section has no counterpart, in which case migration
# from it is not supported.
#
- if [ ! -v "sect_cparts[$src_sect]" ]; then
+ if [[ ! -v "sect_cparts[$src_sect]" ]]; then
info "migration from $src_sect not supported"
return
fi
@@ -1230,9 +1211,9 @@ function migrate_dst ()
# Set the bundle project if unset; otherwise fail if the current file is
# not from the bundle project.
#
- if [ -z "$proj" ]; then
+ if [[ -z "$proj" ]]; then
proj="$fproj"
- elif [ "$fproj" != "$proj" ]; then
+ elif [[ "$fproj" != "$proj" ]]; then
info "'$f' is not in project $proj"
return
fi
@@ -1244,7 +1225,7 @@ function migrate_dst ()
# not be printed in the file list after the migration despite not having
# been actioned.
#
- if [ "$ftype" == "ownership" ]; then
+ if [[ "$ftype" == "ownership" ]]; then
info "skipping '$f'"
unset "bundle_files[$i]"
fi
@@ -1252,7 +1233,7 @@ function migrate_dst ()
# Fail if there were no package archives in `bundle_files`.
#
- if [ "${#bundle_files[@]}" -eq 0 ]; then
+ if [[ "${#bundle_files[@]}" -eq 0 ]]; then
info "no package archives selected"
return
fi
@@ -1292,7 +1273,7 @@ function migrate_dst ()
# Update the commit message.
#
- if [ "${#rv[@]}" -eq 0 ]; then
+ if [[ "${#rv[@]}" -eq 0 ]]; then
cmsg+=" move $name/$version"$'\n'
else
local v
@@ -1313,7 +1294,7 @@ function migrate_dst ()
# file is removed, so this does not need to be done in migrate_src().)
#
local d="$dst_dir/$src_sect_dir/$proj/"
- if [ -z "$(ls -A "$d")" ]; then
+ if [[ -z "$(ls -A "$d")" ]]; then
rmdir "$d"
fi
@@ -1387,7 +1368,7 @@ function check_drop_ownership_consistency () # <proj>
local s
for s in "${sections[@]}"; do
local pd="$rd/$s/$proj" # Project directory.
- if [ -d "$pd" ]; then
+ if [[ -d "$pd" ]]; then
local f
while read f; do
local frel="${f#$rd/}" # Path made relative to repo dir.
@@ -1424,7 +1405,7 @@ function check_drop_ownership_consistency () # <proj>
source "$rd/submit.config.bash"
local pd="$rd/$owners/$proj" # Project directory.
- if [ -d "$pd" ]; then
+ if [[ -d "$pd" ]]; then
local f
while read f; do
f="${f#$rd/}" # Make path relative to repo dir.
@@ -1457,7 +1438,7 @@ associated packages and/or package ownership"
;;
*/package-owner.manifest)
local pname="$(basename $(dirname "$f"))"
- if [ -v "unsel_pkg_names[$pname]" ]; then
+ if [[ -v "unsel_pkg_names[$pname]" ]]; then
info "cannot drop package ownership without associated packages"
return
fi
@@ -1521,7 +1502,7 @@ function drop ()
{
operation_result=
- if [ "$mode" == "stable" ]; then
+ if [[ "$mode" == "stable" ]]; then
info "dropping files from $mode not supported"
return
fi
@@ -1555,7 +1536,7 @@ function drop ()
local ftype="${fi[0]}" # Current file's type.
local fproj="${fi[1]}" # Current file's project.
- if [ "$ftype" == "ownership" ]; then
+ if [[ "$ftype" == "ownership" ]]; then
# Ask whether or not this ownership manifest should be dropped. Add it
# to `owns` if the user confirmed or, if the user declined, skip it by
# not adding it to `owns` and by removing it from `bundle_files` (to
@@ -1567,13 +1548,13 @@ function drop ()
read -p "drop '$f'? [y/n]: " opt
done
- if [ "$opt" == y ]; then
+ if [[ "$opt" == y ]]; then
owns+=("$f")
else
info "skipping '$f'"
unset "bundle_files[$i]"
fi
- elif [ "$ftype" == "archive" ]; then
+ elif [[ "$ftype" == "archive" ]]; then
pkgs+=("$f")
local fsect_dir="${fi[2]}" # Section dir from file path.
@@ -1583,9 +1564,9 @@ function drop ()
# Set the bundle section name if unset; otherwise fail if the current
# package archive is not from the bundle section.
#
- if [ -z "$sect" ]; then
+ if [[ -z "$sect" ]]; then
sect="$fsect"
- elif [ "$fsect" != "$sect" ]; then
+ elif [[ "$fsect" != "$sect" ]]; then
info "'$f' is not in section $sect"
return
fi
@@ -1594,9 +1575,9 @@ function drop ()
# Set the bundle project if unset; otherwise fail if the current file is
# not from the bundle project.
#
- if [ -z "$proj" ]; then
+ if [[ -z "$proj" ]]; then
proj="$fproj"
- elif [ "$fproj" != "$proj" ]; then
+ elif [[ "$fproj" != "$proj" ]]; then
info "'$f' is not in project $proj"
return
fi
@@ -1620,7 +1601,7 @@ function drop ()
#
local reason=
info
- while [ -z "$reason" ]; do
+ while [[ -z "$reason" ]]; do
read -p "reason for dropping: " reason
done
@@ -1628,7 +1609,7 @@ function drop ()
# package archive in the bundle.
#
local cmsg= # Commit message.
- if [ "${#pkgs[@]}" -ne 0 ]; then # Bundle contains package archive(s).
+ if [[ "${#pkgs[@]}" -ne 0 ]]; then # Bundle contains package archive(s).
cmsg="Drop $proj from $sect ($reason)"$'\n\n'
else # Bundle contains only ownership manifests.
cmsg="Drop $proj ownership ($reason)"$'\n\n'
@@ -1696,7 +1677,7 @@ function push ()
error "push to $dst_repo_name failed"
fi
- if [ "$mode" == "source" ] && ! run git -C "$src_dir" push; then
+ if [[ "$mode" == "source" ]] && ! run git -C "$src_dir" push; then
error "push to $src_repo_name failed"
fi
}
@@ -1793,7 +1774,7 @@ function split_commits ()
local fsel=()
while true; do
- if [ "${#bundle_files[@]}" -ne 0 ]; then
+ if [[ "${#bundle_files[@]}" -ne 0 ]]; then
# Print the commits followed by their files. Because `bundle_files` is
# grouped by commit we know we are on a new commit when the current
# file's commit hash differs from that of its predecessor.
@@ -1804,7 +1785,7 @@ function split_commits ()
local f="${bundle_files[$i]}" # Current file.
local fh="${file_commits[$f]}" # Current file's commit hash.
- if [ "$fh" != "$h" ]; then # New commit so first print its heading.
+ if [[ "$fh" != "$h" ]]; then # New commit so first print its heading.
h="$fh"
printf "\n%s %s\n\n" "$fh" "$(commit_subject "$fh")" >&2
fi
@@ -1814,7 +1795,7 @@ function split_commits ()
local sz= # File size.
local fi
src_path_info "$f" | readarray -t fi
- if [ "${fi[0]}" == "archive" ]; then
+ if [[ "${fi[0]}" == "archive" ]]; then
sz=" $(file_size "$f")"
fi
@@ -1859,7 +1840,7 @@ function split_commits ()
{
local opres="$1"
- if [ "$opres" ]; then
+ if [[ "$opres" ]]; then
# Remove the selected/actioned files from `unactioned_files`.
#
local i
@@ -1891,7 +1872,7 @@ function split_commits ()
#
[0-9]*)
if [[ ("$opt" =~ ^[1-9][0-9]*$) && -v "bundle_files[$opt-1]" ]]; then
- if [ ! "$(contains "$opt" "${fsel[@]}")" ]; then
+ if [[ ! "$(contains "$opt" "${fsel[@]}")" ]]; then
fsel+=("$opt")
info "file $opt added to selection"
else
@@ -1904,9 +1885,9 @@ function split_commits ()
# Migrate selected files.
#
m)
- if [ "${#fsel[@]}" -ne 0 ]; then
+ if [[ "${#fsel[@]}" -ne 0 ]]; then
collect_selected_files
- if [ "$mode" == "source" ]; then
+ if [[ "$mode" == "source" ]]; then
migrate_src
else
migrate_dst
@@ -1914,7 +1895,7 @@ function split_commits ()
update_bundle_files "$operation_result"
- if [ "$operation_result" ]; then
+ if [[ "$operation_result" ]]; then
fsel=()
need_push=true
break
@@ -1926,13 +1907,13 @@ function split_commits ()
# Drop selected files.
#
d)
- if [ "${#fsel[@]}" -ne 0 ]; then
+ if [[ "${#fsel[@]}" -ne 0 ]]; then
collect_selected_files
drop
update_bundle_files "$operation_result"
- if [ "$operation_result" ]; then
+ if [[ "$operation_result" ]]; then
fsel=()
need_push=true
break
@@ -1993,12 +1974,12 @@ while true; do
# performing complex house-keeping, after certain operations (e.g.,
# migration) we will just re-initialize the state from scratch.
#
- if [ "$init" ]; then
+ if [[ "$init" ]]; then
init_globals
- if [ "${#pending_seq[@]}" -eq 0 ]; then
+ if [[ "${#pending_seq[@]}" -eq 0 ]]; then
info "good news, nothing to manage"
- if [ ! "$need_push" ]; then
+ if [[ ! "$need_push" ]]; then
exit 0
fi
fi
@@ -2039,7 +2020,7 @@ while true; do
src_path_info "$f" | readarray -t fi
ftype="${fi[0]}"
- if [ "$ftype" == "unmanaged" ]; then
+ if [[ "$ftype" == "unmanaged" ]]; then
# File is unmanaged (and may or may not exist).
#
info "? $f"
@@ -2057,9 +2038,9 @@ while true; do
# Note that, in destination-management mode, there can be no ownership
# manifests in `file_commits`.
#
- if [ "${file_commits[$f]}" == "$h" ]; then
+ if [[ "${file_commits[$f]}" == "$h" ]]; then
info " $f $sz" # Last added or moved by the current commit.
- elif [ -v "file_commits[$f]" ]; then
+ elif [[ -v "file_commits[$f]" ]]; then
info "! $f $sz" # Deleted and added back by subsequent commits.
elif [[ ("$mode" == "source") || ("$ftype" != "ownership") ]]; then
# File was deleted and never added again and, if we're in
@@ -2107,7 +2088,7 @@ while true; do
#
[0-9]*)
if [[ ("$opt" =~ ^[1-9][0-9]*$) && -v "pending_seq[$opt-1]" ]]; then
- if [ ! "$(contains "$opt" "${bundle[@]}")" ]; then
+ if [[ ! "$(contains "$opt" "${bundle[@]}")" ]]; then
bundle+=("$opt")
info "commit $opt (${pending_seq[$opt-1]}) \
added to selected bundle"
@@ -2121,16 +2102,16 @@ added to selected bundle"
# Migrate the commit bundle.
#
m)
- if [ "${#bundle[@]}" -ne 0 ]; then
+ if [[ "${#bundle[@]}" -ne 0 ]]; then
collect_bundle_files # Prints error if `bundle_files` left empty.
- if [ "${#bundle_files[@]}" -ne 0 ]; then
- if [ "$mode" == "source" ]; then
+ if [[ "${#bundle_files[@]}" -ne 0 ]]; then
+ if [[ "$mode" == "source" ]]; then
migrate_src
else
migrate_dst
fi
- if [ "$operation_result" ]; then
+ if [[ "$operation_result" ]]; then
need_push=true
init=true
break
@@ -2143,12 +2124,12 @@ added to selected bundle"
# Drop the commit bundle.
#
d)
- if [ "${#bundle[@]}" -ne 0 ]; then
+ if [[ "${#bundle[@]}" -ne 0 ]]; then
collect_bundle_files # Prints error if `bundle_files` left empty.
- if [ "${#bundle_files[@]}" -ne 0 ]; then
+ if [[ "${#bundle_files[@]}" -ne 0 ]]; then
drop
- if [ "$operation_result" ]; then
+ if [[ "$operation_result" ]]; then
need_push=true
init=true
break
@@ -2162,10 +2143,10 @@ added to selected bundle"
# bundle's files).
#
s)
- if [ "${#bundle[@]}" -ne 0 ]; then
+ if [[ "${#bundle[@]}" -ne 0 ]]; then
collect_bundle_files # Prints error if `bundle_files` left empty.
- if [ "${#bundle_files[@]}" -ne 0 ]; then
+ if [[ "${#bundle_files[@]}" -ne 0 ]]; then
split_commits
# Note that the global state is re-initialized even if nothing was
@@ -2200,7 +2181,7 @@ added to selected bundle"
# Quit.
#
q)
- if [ ! "$need_push" ]; then
+ if [[ ! "$need_push" ]]; then
exit 0
fi