@beplus/be 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/be +83 -101
  2. package/package.json +12 -5
package/bin/be CHANGED
@@ -64,7 +64,7 @@ function n_grep() {
64
64
  # Setup and state
65
65
  #
66
66
 
67
- VERSION="v0.7.0"
67
+ VERSION="v0.9.0"
68
68
 
69
69
  BE_PREFIX="${BE_PREFIX-/usr/local}"
70
70
  BE_PREFIX=${BE_PREFIX%/}
@@ -83,18 +83,6 @@ BE_DOWNLOAD_MIRROR=${BE_DOWNLOAD_MIRROR:-https://github.com/beplus/cli/releases/
83
83
  BE_DOWNLOAD_MIRROR=${BE_DOWNLOAD_MIRROR%/}
84
84
  readonly BE_DOWNLOAD_MIRROR
85
85
 
86
- # Using xz instead of gzip is enabled by default, if xz compatibility checks pass.
87
- # User may set BE_USE_XZ to 0 to disable, or set to anything else to enable.
88
- # May also be overridden by command line flags.
89
-
90
- # Normalise external values to true/false
91
- if [[ "${BE_USE_XZ}" = "0" ]]; then
92
- BE_USE_XZ="false"
93
- elif [[ -n "${BE_USE_XZ+defined}" ]]; then
94
- BE_USE_XZ="true"
95
- fi
96
- # Not setting to readonly. Overriden by CLI flags, and update_xz_settings_for_version.
97
-
98
86
  BE_MAX_REMOTE_MATCHES=${BE_MAX_REMOTE_MATCHES:-20}
99
87
 
100
88
  g_mirror_url=${BE_MIRROR}
@@ -188,22 +176,6 @@ display_major_version() {
188
176
  echo "${version}"
189
177
  }
190
178
 
191
- #
192
- # Synopsis: update_xz_settings_for_version numeric-version
193
- # Globals modified:
194
- # - BE_USE_XZ
195
- #
196
-
197
- function update_xz_settings_for_version() {
198
- # tarballs in xz format were available in later version of iojs, but KISS and only use xz from v4.
199
- if [[ "${BE_USE_XZ}" = "true" ]]; then
200
- local major_version="$(display_major_version "$1")"
201
- if [[ "${major_version}" -lt 4 ]]; then
202
- BE_USE_XZ="false"
203
- fi
204
- fi
205
- }
206
-
207
179
  #
208
180
  # Synopsis: update_arch_settings_for_version numeric-version
209
181
  # Globals modified:
@@ -327,7 +299,6 @@ Options:
327
299
  -a, --arch Override system architecture
328
300
  --all ls-remote displays all matches instead of last 20
329
301
  --insecure Turn off certificate checking for https requests (may be needed from behind a proxy server)
330
- --use-xz/--no-use-xz Override automatic detection of xz support and enable/disable use of xz compressed beplus CLI downloads.
331
302
 
332
303
  Aliases:
333
304
 
@@ -383,28 +354,23 @@ display_be_version() {
383
354
 
384
355
  #
385
356
  # Synopsis: set_active_beplus
386
- # Checks cached downloads for a binary matching the active beplus CLI.
357
+ # Checks cached downloads for the one the installed beplus CLI was copied from: activate copies
358
+ # <cache>/beplus/<version>/beplus to $BE_PREFIX/bin/beplus, so the two files are identical.
387
359
  # Globals modified:
388
360
  # - g_active_beplus
389
361
  #
390
362
 
391
363
  function set_active_beplus() {
392
364
  g_active_beplus=
393
- local beplus_path="$(command -v beplus)"
394
- if [[ -x "${beplus_path}" ]]; then
395
- local installed_version=$(beplus --version)
396
- installed_version=${installed_version#v}
397
- for dir in "${CACHE_DIR}"/*/ ; do
398
- local folder_name="${dir%/}"
399
- folder_name="${folder_name##*/}"
400
- if diff &> /dev/null \
401
- "${CACHE_DIR}/${folder_name}/${installed_version}/bin/beplus" \
402
- "${beplus_path}" ; then
403
- g_active_beplus="${folder_name}/${installed_version}"
404
- break
405
- fi
406
- done
407
- fi
365
+ local cached
366
+ for cached in "${CACHE_DIR}"/*/*/beplus; do
367
+ # cmp stops at the first difference; diff may read both binaries (~110 MB each) whole.
368
+ if cmp -s "${cached}" "${BE_PREFIX}/bin/beplus"; then
369
+ cached="${cached#"${CACHE_DIR}/"}"
370
+ g_active_beplus="${cached%/beplus}"
371
+ break
372
+ fi
373
+ done
408
374
  }
409
375
 
410
376
  #
@@ -638,18 +604,10 @@ install() {
638
604
  get_latest_resolved_version "$1" || return 2
639
605
  version="${g_target_beplus}"
640
606
  [[ -n "${version}" ]] || abort "no version found for '$1'"
641
- update_xz_settings_for_version "${version}"
642
607
  update_arch_settings_for_version "${version}"
643
608
 
644
609
  local dir="${CACHE_DIR}/${g_mirror_folder_name}/${version}"
645
610
 
646
- # Note: decompression flags ignored with default Darwin tar which autodetects.
647
- if test "$BE_USE_XZ" = "true"; then
648
- local tarflag="-Jx"
649
- else
650
- local tarflag="-zx"
651
- fi
652
-
653
611
  if test -d "$dir"; then
654
612
  if [[ ! -e "$dir/be.lock" ]] ; then
655
613
  if [[ "$DOWNLOAD" == "false" ]] ; then
@@ -664,6 +622,15 @@ install() {
664
622
  local url="$(tarball_url "$version")"
665
623
  is_ok "${url}" || abort "download preflight failed for '$version' (${url})"
666
624
 
625
+ # The release publishes SHA256SUMS beside its tarballs. Read this tarball's line before
626
+ # downloading it, and extract only a download that matches it. 2.x lists `<hash> <name>`, as
627
+ # sha256sum writes it; v1.0.5 lists `<name>: <hash>`.
628
+ local sums_url="${url%/*}/SHA256SUMS"
629
+ local sums
630
+ sums="$(do_get_index "${sums_url}")" || abort "failed to download SHA256SUMS for $version (${sums_url})"
631
+ local checksum="$(echo "${sums}" | awk -v name="${url##*/}" '$2 == name { print $1; exit } $1 == name ":" { print $2; exit }')"
632
+ [[ -n "${checksum}" ]] || abort "no checksum for ${url##*/} in ${sums_url}"
633
+
667
634
  log mkdir "$dir"
668
635
  mkdir -p "$dir" || abort "sudo required (or change ownership, or define BE_PREFIX)"
669
636
  touch "$dir/be.lock"
@@ -671,15 +638,21 @@ install() {
671
638
  cd "${dir}" || abort "Failed to cd to ${dir}"
672
639
 
673
640
  log fetch "$url"
674
- do_get "${url}" | tar "$tarflag" --no-same-owner -f - # --strip-components=1
675
- pipe_results=( "${PIPESTATUS[@]}" )
676
- if [[ "${pipe_results[0]}" -ne 0 ]]; then
641
+ local archive="${dir}/${url##*/}"
642
+ if ! do_get "${url}" > "${archive}"; then
643
+ rm -f "${archive}"
677
644
  abort "failed to download archive for $version"
678
645
  fi
679
- if [[ "${pipe_results[1]}" -ne 0 ]]; then
680
- abort "failed to extract archive for $version"
681
- fi
682
646
  [ "$GET_SHOWS_PROGRESS" = "true" ] && erase_line
647
+ local download_checksum="$(display_sha256 "${archive}")"
648
+ if [[ "${download_checksum}" != "${checksum}" ]]; then
649
+ rm -f "${archive}"
650
+ abort "checksum mismatch for ${url}: ${sums_url} lists ${checksum}, the download is ${download_checksum}"
651
+ fi
652
+ tar -zx --no-same-owner -f "${archive}" # --strip-components=1
653
+ local tar_status=$?
654
+ rm -f "${archive}"
655
+ [[ "${tar_status}" -eq 0 ]] || abort "failed to extract archive for $version"
683
656
  rm -f "$dir/be.lock"
684
657
 
685
658
  disable_pax_mprotect bin/beplus
@@ -713,6 +686,23 @@ function do_get() {
713
686
  fi
714
687
  }
715
688
 
689
+ #
690
+ # Synopsis: display_sha256 file
691
+ # sha256sum where it exists, otherwise shasum, which macOS has. Both hash stdin rather than a
692
+ # named file: given a name with a backslash in it, they escape it and put a backslash before the
693
+ # hash.
694
+ #
695
+
696
+ function display_sha256() {
697
+ local line
698
+ if command -v sha256sum &> /dev/null; then
699
+ line="$(sha256sum < "$1")"
700
+ else
701
+ line="$(shasum -a 256 < "$1")"
702
+ fi
703
+ echo "${line%% *}"
704
+ }
705
+
716
706
  #
717
707
  # Synopsis: do_get_index [option...] url
718
708
  # Call curl or wget with combination of global and passed options,
@@ -836,30 +826,6 @@ function is_ok() {
836
826
  fi
837
827
  }
838
828
 
839
- #
840
- # Synopsis: can_use_xz
841
- # Test system to see if xz decompression is supported by tar.
842
- #
843
-
844
- function can_use_xz() {
845
- # Be conservative and only enable if xz is likely to work. Unfortunately we can't directly query tar itself.
846
- # For research, see https://github.com/shadowspawn/nvh/issues/8
847
- local uname_s="$(uname -s)"
848
- if [[ "${uname_s}" = "Linux" ]] && command -v xz &> /dev/null ; then
849
- # tar on linux is likely to support xz if it is available as a command
850
- return 0
851
- elif [[ "${uname_s}" = "Darwin" ]]; then
852
- local macos_version="$(sw_vers -productVersion)"
853
- local macos_major_version="$(echo "${macos_version}" | cut -d '.' -f 1)"
854
- local macos_minor_version="$(echo "${macos_version}" | cut -d '.' -f 2)"
855
- if [[ "${macos_major_version}" -gt 10 || "${macos_minor_version}" -gt 8 ]]; then
856
- # tar on recent Darwin has xz support built-in
857
- return 0
858
- fi
859
- fi
860
- return 2 # not supported
861
- }
862
-
863
829
  #
864
830
  # Synopsis: display_tarball_platform
865
831
  #
@@ -926,10 +892,8 @@ function tarball_url() {
926
892
  # Artifact version (filename MUST NOT contain +suffix)
927
893
  local artifact_version="${version%%+*}"
928
894
 
929
- local ext="gz"
930
- [ "$BE_USE_XZ" = "true" ] && ext="xz"
931
-
932
- echo "${g_mirror_url}/v${url_version}/beplus-cli-v${artifact_version}-$(display_tarball_platform).tar.${ext}"
895
+ # The beplus CLI release publishes .tar.gz only.
896
+ echo "${g_mirror_url}/v${url_version}/beplus-cli-v${artifact_version}-$(display_tarball_platform).tar.gz"
933
897
  }
934
898
 
935
899
  #
@@ -1156,17 +1120,41 @@ function display_remote_versions() {
1156
1120
  # local index_url="https://beplus.s3.amazonaws.com/cli/releases.json"
1157
1121
  local index_url="${BE_RELEASE_INDEX_URL:-https://beplus.s3.amazonaws.com/cli/releases.json}"
1158
1122
 
1159
- # Select the release names to consider. GitHub lists the newest release
1160
- # first, including any in-progress pre-releases (e.g. a v2 published while v1
1161
- # is still the current release), so 'latest'/'current'/'stable' filter those
1162
- # out to resolve to the newest official release.
1123
+ # Select the release names to consider. 'latest'/'current'/'stable' mean the newest official
1124
+ # release, so they skip pre-releases and drafts.
1163
1125
  local jq_release_filter='.[]'
1164
1126
  if [[ -n "${official_only}" ]]; then
1165
1127
  jq_release_filter='.[] | select(.prerelease != true and .draft != true)'
1166
1128
  fi
1167
1129
 
1130
+ # ...then order them ourselves, because no index promises to. The GitHub Releases API sorts by
1131
+ # created_at, and every beplus/cli release shares one (the tags all point at that repo's
1132
+ # unchanged default-branch HEAD), so the list ties and comes back in no particular order —
1133
+ # which had `be 2` resolving to a stage build published before the prod one. Callers take the
1134
+ # first match, so the sort is what makes "first" mean "newest".
1135
+ #
1136
+ # SemVer §11 sort key: major, minor, patch, then "has no pre-release" (a release outranks the
1137
+ # pre-releases it was promoted from), then the pre-release identifiers — numeric ones compared
1138
+ # numerically and ranked below alphanumeric ones, a longer run of identifiers winning a shared
1139
+ # prefix. A name that is not a version sorts last rather than aborting the pipeline.
1140
+ #
1141
+ # This is NOT `sort -V`: GNU version sort ranks 2.0.0-dev.40 *above* 2.0.0, the opposite of
1142
+ # SemVer, which is exactly backwards for a promotion pipeline.
1143
+ local jq_semver_key='def semver_key:
1144
+ ltrimstr("v")
1145
+ | if test("^[0-9]+\\.[0-9]+\\.[0-9]+([-+].*)?$")
1146
+ then (capture("^(?<ma>[0-9]+)\\.(?<mi>[0-9]+)\\.(?<pa>[0-9]+)(?:-(?<pre>[^+]+))?(?:\\+.*)?$")
1147
+ | [1, (.ma|tonumber), (.mi|tonumber), (.pa|tonumber),
1148
+ (if .pre == null then 1 else 0 end),
1149
+ (if .pre == null then []
1150
+ else (.pre | split(".")
1151
+ | map(if test("^[0-9]+$") then [0, (.|tonumber), ""] else [1, 0, .] end))
1152
+ end)])
1153
+ else [0, 0, 0, 0, 0, []]
1154
+ end;'
1155
+
1168
1156
  do_get_index "${index_url}" \
1169
- | jq -r "${jq_release_filter} | .name" \
1157
+ | jq -r "${jq_semver_key} [ ${jq_release_filter} | .name ] | sort_by(semver_key) | reverse | .[]" \
1170
1158
  | n_grep -E "${match}" \
1171
1159
  | awk "NR<=${match_count}" \
1172
1160
  | cut -f 1 \
@@ -1193,7 +1181,8 @@ function delete_with_echo() {
1193
1181
 
1194
1182
  uninstall_installed() {
1195
1183
  while true; do
1196
- read -r -p "Do you wish to delete beplus CLI from ${BE_PREFIX}? " yn
1184
+ # End of input answers no.
1185
+ read -r -p "Do you wish to delete beplus CLI from ${BE_PREFIX}? " yn || yn="n"
1197
1186
  case $yn in
1198
1187
  [Yy]* ) break ;;
1199
1188
  [Nn]* ) exit ;;
@@ -1408,8 +1397,6 @@ while [[ $# -ne 0 ]]; do
1408
1397
  -q|--quiet) set_quiet ;;
1409
1398
  -d|--download) DOWNLOAD="true" ;;
1410
1399
  --insecure) set_insecure ;;
1411
- --use-xz) BE_USE_XZ="true" ;;
1412
- --no-use-xz) BE_USE_XZ="false" ;;
1413
1400
  --latest) display_remote_versions latest; exit ;;
1414
1401
  --stable) display_remote_versions latest; exit ;;
1415
1402
  -a|--arch) shift; set_arch "$1";; # set arch and continue
@@ -1428,11 +1415,6 @@ while [[ $# -ne 0 ]]; do
1428
1415
  shift
1429
1416
  done
1430
1417
 
1431
- if [[ -z "${BE_USE_XZ+defined}" ]]; then
1432
- BE_USE_XZ="true" # Default to using xz
1433
- can_use_xz || BE_USE_XZ="false"
1434
- fi
1435
-
1436
1418
  set -- "${unprocessed_args[@]}"
1437
1419
 
1438
1420
  if test $# -eq 0; then
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@beplus/be",
3
3
  "description": "Interactively Manage beplus CLI Versions",
4
- "version": "0.7.0",
4
+ "version": "0.9.0",
5
5
  "author": "Igor Lamos <igor@be.plus>",
6
6
  "homepage": "https://github.com/beplus/be",
7
7
  "bugs": "https://github.com/beplus/be",
@@ -13,15 +13,22 @@
13
13
  ],
14
14
  "repository": {
15
15
  "type": "git",
16
- "url": "git://github.com/beplus/be.git"
16
+ "url": "git+https://github.com/beplus/be.git"
17
+ },
18
+ "publishConfig": {
19
+ "registry": "https://registry.npmjs.org/",
20
+ "@beplus:registry": "https://registry.npmjs.org/",
21
+ "access": "public"
17
22
  },
18
23
  "scripts": {
19
- "test": "test/bin/run-all-tests"
24
+ "test": "test/bin/run-all-tests",
25
+ "test:host": "PATH=\"$PWD/bin:$PATH\" bats test/tests",
26
+ "lint": "shellcheck -S warning bin/be bin/bump scripts/install.sh scripts/release/*.sh"
20
27
  },
21
28
  "devDependencies": {
22
29
  "bats": "1.8.2",
23
- "bats-assert": "github:bats-core/bats-assert",
24
- "bats-support": "github:bats-core/bats-support"
30
+ "bats-assert": "2.2.4",
31
+ "bats-support": "0.3.0"
25
32
  },
26
33
  "preferGlobal": true,
27
34
  "os": [