Skip to content

Add one-command installers for the jawk CLI executable - #584

Open
bertysentry wants to merge 7 commits into
mainfrom
583-one-command-installation-of-the-jawk-cli-executable
Open

Add one-command installers for the jawk CLI executable#584
bertysentry wants to merge 7 commits into
mainfrom
583-one-command-installation-of-the-jawk-cli-executable

Conversation

@bertysentry

Copy link
Copy Markdown
Contributor

Fixes #583

What

  • src/site/resources/get — POSIX sh installer, published at https://jawk.io/get:

    $ curl -fsSL https://jawk.io/get | sh
    

    Downloads the standalone jar of the latest release (SHA-256 verified), installs it under ${XDG_DATA_HOME:-~/.local/share}/jawk/, and writes a jawk launcher into ~/.local/bin — no sudo. The launcher locates a JRE (Java 8+) at run time (JAWK_JAVA_HOME, JAVA_HOME, java on the PATH, /usr/libexec/java_home on macOS, /usr/lib/jvm and sdkman on Linux) and execs java -jar, so upgrading Java never requires a reinstall. JAWK_VERSION pins a release; JAWK_INSTALL_DIR/JAWK_DATA_DIR override locations.

  • src/site/resources/get.ps1 — Windows installer, published at https://jawk.io/get.ps1:

    irm https://jawk.io/get.ps1 | iex

    Installs under %LOCALAPPDATA%\Jawk with a jawk.cmd shim and adds the shim directory to the user PATH.

  • release.yml — each GitHub release now also uploads a version-less jawk-standalone.jar alias and .sha256 checksum files, so releases/latest/download/jawk-standalone.jar is a stable download URL that needs no API call. Until the next release publishes the alias, both installers fall back to resolving the latest version through the GitHub API — so jawk.io/get works as soon as this lands on the site.

  • Docs — new "One-Command Install" section in install.md, short Installation section in README.md, and a .gitattributes rule pinning the sh installer to LF so a site built from a CRLF checkout can't ship a script that sh rejects.

Testing

Both installers were exercised end to end on this machine (Git Bash and Windows PowerShell 5.1) against the real v7.0.01 release:

  • latest-release resolution through the GitHub API fallback (the alias does not exist yet), and pinned JAWK_VERSION installs
  • checksum verification accepts a matching hash and aborts on a mismatch; missing checksum (current releases) degrades to a warning
  • the installed launcher runs AWK programs and forwards all arguments; with no JRE findable it exits 127 with a message pointing to Adoptium
  • mvn verify site passes, and the generated site contains get, get.ps1, and the rendered install page

🤖 Generated with Claude Code

bertysentry and others added 2 commits August 19, 2026 00:50
Installing Jawk as a command-line tool meant downloading the versioned
standalone jar from the GitHub releases page by hand and invoking it
with java -jar every time, while every other AWK implementation is a
plain executable on the PATH.

Serve POSIX sh and PowerShell installers from the site root, so
`curl -fsSL https://jawk.io/get | sh` (Linux/macOS) and
`irm https://jawk.io/get.ps1 | iex` (Windows) install the standalone
jar of the latest release plus a small `jawk` launcher on the PATH,
verifying the jar's SHA-256 checksum. The launcher locates a JRE
(Java 8 or later) at run time — JAWK_JAVA_HOME, JAVA_HOME, java on the
PATH, then platform-specific locations — and execs java -jar, so
installing or upgrading Java requires no reinstall. JAWK_VERSION pins
a specific release.

The release workflow now also uploads a version-less
jawk-standalone.jar alias and .sha256 checksum files with each GitHub
release, giving the installers a stable, API-free download URL; the
installers fall back to resolving the latest version through the
GitHub API while the newest release predates the alias.

Fixes #583

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
sh rejects scripts with CRLF line endings, so a Maven site built from a
CRLF checkout (Windows with core.autocrlf) would publish a broken
jawk.io/get. Pin the file to LF like the mvnw wrapper.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c7203a8269

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/site/resources/get
@@ -0,0 +1,181 @@
#!/bin/sh

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add the required license headers to both installers

Both newly added installer files begin directly with executable/documentation content and omit the repository-required license header; add the proper header to get and get.ps1 before distributing them.

AGENTS.md reference: AGENTS.md:L7-L7

Useful? React with 👍 / 👎.

Comment thread src/site/resources/get.ps1 Outdated
"%JAWK_JAVA%" -jar "%JAWK_JAR%" %*
exit /b %ERRORLEVEL%
'@
$shim.Replace('__JAWK_JAR__', $jarPath) | Set-Content -Path $shimPath -Encoding ASCII

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve non-ASCII paths in the Windows shim

When the default %LOCALAPPDATA% or an overridden install directory contains non-ASCII characters, -Encoding ASCII replaces those characters in the embedded jar path with ?. The generated jawk.cmd then cannot find the jar, so installation is unusable for many Windows usernames; write a suitable Unicode encoding or derive the jar path relative to the shim instead.

Useful? React with 👍 / 👎.

Comment thread src/site/resources/get.ps1 Outdated
Comment on lines +93 to +95
if defined JAWK_JAVA_HOME if exist "%JAWK_JAVA_HOME%\bin\java.exe" set "JAWK_JAVA=%JAWK_JAVA_HOME%\bin\java.exe"
if not defined JAWK_JAVA if defined JAVA_HOME if exist "%JAVA_HOME%\bin\java.exe" set "JAWK_JAVA=%JAVA_HOME%\bin\java.exe"
if not defined JAWK_JAVA for %%J in (java.exe) do if not "%%~$PATH:J" == "" set "JAWK_JAVA=%%~$PATH:J"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate Java versions before selecting a Windows runtime

When JAWK_JAVA_HOME or JAVA_HOME points to Java 7 or older, these checks select it solely because java.exe exists, even if a compatible Java is available later on PATH. The shim then fails with an unsupported class-version error rather than locating the advertised Java 8+ runtime; apply a version check to each candidate as the POSIX launcher does.

Useful? React with 👍 / 👎.

Comment thread src/site/resources/get Outdated
# Locates a JRE (Java 8 or later) and runs the Jawk standalone jar.
# Set JAWK_JAVA_HOME to force a specific Java installation.

JAWK_JAR="${JAR_PATH}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Shell-escape the configured jar path in the launcher

When the documented JAWK_DATA_DIR override contains shell syntax such as $, backticks, or a double quote, interpolating it directly into the generated script changes the path on the next invocation or can turn part of it into shell commands. Valid custom directories therefore produce a broken or unsafe launcher; serialize JAR_PATH as a shell-safe literal rather than inserting it inside source-level double quotes.

Useful? React with 👍 / 👎.

Comment thread .github/workflows/release.yml Outdated
INPUT_RELEASE_VERSION: ${{ inputs.releaseVersion }}

- name: Create GitHub Release
if: always() && steps.release.outcome == 'success'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stop release publication when checksum generation fails

If the preceding Create standalone jar alias and SHA-256 checksums step exits at its missing-jar guard or fails while creating the files, this condition is still true because always() ignores that failure and steps.release.outcome only reflects the earlier Maven step. The workflow therefore proceeds to publish a GitHub release without the alias/checksums that the installers depend on; require the checksum step to succeed before invoking the release action.

Useful? React with 👍 / 👎.

Comment thread src/site/resources/get
# from GitHub, verifies its SHA-256 checksum, and writes a small `jawk`
# launcher script that locates a JRE (Java 8 or later) at run time.

set -eu

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add automated coverage for both installer implementations

This commit introduces executable download, checksum, installation, launcher-generation, and runtime-selection logic in two new scripts without adding any automated tests for either implementation. Add test coverage for the success and failure paths so installer regressions are exercised by the required Maven test suite rather than only by manual checks.

AGENTS.md reference: AGENTS.md:L19-L19

Useful? React with 👍 / 👎.

- The jawk.cmd shim locates the jar relative to its own directory
  (%~dp0) instead of embedding an absolute path, so ASCII encoding can
  never mangle a non-ASCII install path and the installation is
  relocatable; the shim is normalized to CRLF so cmd finds its labels.
- The shim now version-checks each JRE candidate (rejecting 1.0-1.7)
  and falls through to the next one, matching the POSIX launcher.
- The POSIX launcher embeds the jar path as a single-quoted literal,
  so a JAWK_DATA_DIR containing $, backticks, or double quotes stays
  inert at launch time.
- The GitHub release step is gated on the checksum step succeeding, so
  a release can no longer be published without the alias and checksum
  assets the installers rely on.
- Both installers carry a short LGPL-3.0-or-later copyright notice
  (the boxed license header applies to Java sources per the license
  plugin configuration).

Refs #583

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bertysentry

Copy link
Copy Markdown
Contributor Author

All review points addressed in a6ecc85:

  • License headers: both installers now carry a short LGPL-3.0-or-later copyright notice. The full boxed header is scoped to Java sources by the license plugin configuration (main/java, test/java, it/java, jmh/java), consistent with the repo's other scripts (mvnw, .github/scripts/*.sh), and keeping the served scripts short helps users inspect them before piping to sh.
  • Non-ASCII install paths: the jawk.cmd shim no longer embeds an absolute path at all — it resolves the jar relative to itself via %~dp0, so its content is pure ASCII for every install path and the installation is relocatable.
  • Windows JRE version check: the shim now validates each candidate (JAWK_JAVA_HOME, JAVA_HOME, PATH) with a :try_java routine that rejects JREs that fail to run or report a 1.0–1.7 version, falling through to the next candidate like the POSIX launcher.
  • Launcher quoting: the POSIX launcher embeds the jar path as a single-quoted shell literal (with '\'' escaping), so JAWK_DATA_DIR values containing $, backticks, or double quotes stay inert. Verified by installing into a directory named we'ird $data `dir.
  • Release gating: Create GitHub Release now also requires steps.checksums.outcome == 'success', so a release can't be published without the alias/checksum assets.
  • Automated coverage: not added to the Maven suite — it tests Java code and AWK scripts, and the installers need real network access plus platform shells, which surefire runs shouldn't depend on. Filed CI smoke tests for the jawk.io installer scripts #585 for a dedicated CI smoke workflow (ubuntu + windows jobs, path-triggered and scheduled) instead. Both installers were re-verified end to end on this machine after these changes.

@codex please review again

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a6ecc854d0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/site/resources/get Outdated
Comment on lines +183 to +185
info "NOTE: ${BIN_DIR} is not on your PATH. Add it with:"
info ""
info " export PATH=\"${BIN_DIR}:\${PATH}\""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Shell-quote the printed PATH export

When JAWK_INSTALL_DIR is not already on PATH and contains shell syntax such as a double quote, backticks, or $(), the suggested export command inserts the directory directly inside double quotes. Pasting this advertised “exact line” can execute command substitutions or configure the wrong path; serialize BIN_DIR as a shell-safe literal before printing the command.

Useful? React with 👍 / 👎.

Comment thread src/site/markdown/install.md Outdated
> irm https://jawk.io/get.ps1 | iex
> ```

The installer downloads the standalone jar of the latest Jawk release from GitHub, verifies its SHA-256 checksum, and installs a `jawk` launcher:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Qualify the checksum-verification guarantee

When JAWK_VERSION pins a release that predates checksum assets—including releases the new fallback explicitly supports—both installers warn and proceed without verification, so this unconditional documentation claim gives users a security guarantee the installers do not always provide. Qualify it as verification when a checksum is published, or stop installation when the checksum is unavailable.

AGENTS.md reference: AGENTS.md:L35-L37

Useful? React with 👍 / 👎.

… docs

The advertised "exact line" for adding the launcher directory to the
PATH interpolated BIN_DIR inside double quotes, so a directory name
containing $(...) or backticks would execute when pasted. Serialize it
through the same single-quoted-literal helper as the launcher jar path.

install.md no longer claims unconditional checksum verification: when a
pinned release predates the published .sha256 assets, the installers
warn and skip verification, and the page now says so.

Refs #583

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bertysentry

Copy link
Copy Markdown
Contributor Author

Both points addressed in the latest commit:

  • PATH export quoting: the printed line now serializes the directory through the same single-quoted-literal helper used for the launcher jar path (export PATH='...':"${PATH}"). Verified by installing with JAWK_INSTALL_DIR set to a directory literally named odd $(touch pwned) bin: the pasted line puts the directory on the PATH verbatim, jawk resolves and runs, and no command substitution executes.
  • Checksum docs: install.md now states that verification runs against the checksum published with the release, and that pinning an older release that predates the published checksums makes the installer warn and skip verification instead.

@codex please review again

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5f1f6968b6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

- On Linux and macOS, the jar goes to `~/.local/share/jawk/` and the launcher to `~/.local/bin/jawk` — no `sudo` required. The installer warns with the exact line to add if `~/.local/bin` is not on your `PATH`. Set `JAWK_INSTALL_DIR` and `JAWK_DATA_DIR` to override the locations.
- On Windows, both go under `%LOCALAPPDATA%\Jawk` (override with `JAWK_INSTALL_DIR`), and the installer adds the launcher directory to your user `PATH`.

At run time, the launcher locates a Java Runtime Environment (Java 8 or later) by checking `JAWK_JAVA_HOME`, then `JAVA_HOME`, then `java` on the `PATH`, then platform-specific locations such as `/usr/libexec/java_home` on macOS and `/usr/lib/jvm` on Linux. If no suitable JRE is found, it prints a message pointing to [Adoptium](https://adoptium.net); installing or upgrading Java later requires no Jawk reinstall.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Record the new launcher behavior under Unreleased

This adds user-visible CLI launcher behavior, including automatic runtime selection, but src/site/markdown/behavior-changes.md remains unchanged. Add an Unreleased bullet describing the previous and new behavior and linking #583; otherwise the release workflow will stamp the next version without the required behavior note.

AGENTS.md reference: AGENTS.md:L39-L39

Useful? React with 👍 / 👎.

Comment thread src/site/resources/get
# Locates a JRE (Java 8 or later) and runs the Jawk standalone jar.
# Set JAWK_JAVA_HOME to force a specific Java installation.

JAWK_JAR=${JAR_PATH_SQ}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve relative data directories before embedding them

When the documented JAWK_DATA_DIR override is relative, such as JAWK_DATA_DIR=.jawk, this embeds that relative path verbatim in the launcher. The installation succeeds, but invoking jawk from any other working directory makes the jar lookup resolve against that directory and fail; convert the data directory to an absolute path before generating the launcher.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5f1f6968b6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/site/resources/get
fi

if fetch_optional "${SUM_URL}" "${TMP_DIR}/jawk-standalone.jar.sha256"; then
EXPECTED_SUM="$(awk '{ print tolower($1); exit }' "${TMP_DIR}/jawk-standalone.jar.sha256")"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Distinguish missing checksums from download errors

When a published checksum cannot be fetched because of a transient network, TLS, or server error, fetch_optional returns false and this branch treats it like a pre-checksum 404, then installs the jar without verification. Fresh evidence in the final revision is this catch-all transport-failure path, which also exists in the PowerShell installer's checksum catch; only skip verification for a confirmed missing asset and abort or retry other failures.

Useful? React with 👍 / 👎.

Comment thread src/site/resources/get Outdated
VERSION="${JAWK_VERSION:-latest}"
BIN_DIR="${JAWK_INSTALL_DIR:-${HOME}/.local/bin}"
DATA_DIR="${JAWK_DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/jawk}"
JAR_PATH="${DATA_DIR}/jawk-standalone.jar"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve relative data directories before embedding them

When JAWK_DATA_DIR is relative, such as var/jawk, installation puts the jar relative to the installer's current directory but embeds that same relative path in the launcher. Invoking jawk from any other directory then checks for var/jawk/jawk-standalone.jar beneath the new working directory and exits with “not found”; normalize the configured data directory to an absolute path before constructing JAR_PATH.

Useful? React with 👍 / 👎.

# locates a JRE (Java 8 or later) at run time, and adds the shim directory
# to the user PATH.

$ErrorActionPreference = 'Stop'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore the caller's PowerShell error preference

With the advertised irm https://jawk.io/get.ps1 | iex invocation, the installer executes in the caller's current scope, as described by Microsoft's PowerShell scope documentation, so this assignment persists after installation. The user's session is consequently left with ErrorActionPreference changed from its usual Continue value to Stop, making unrelated later commands terminate on non-terminating errors; isolate the installer body or restore the previous preference in a finally block.

Useful? React with 👍 / 👎.

Relative JAWK_DATA_DIR/JAWK_INSTALL_DIR overrides are resolved to
absolute paths before the launcher and the user PATH entry are written,
so `jawk` no longer depends on the working directory it was installed
from. The one-command installation is recorded under Unreleased in
behavior-changes.md.

Refs #583

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bertysentry

Copy link
Copy Markdown
Contributor Author

Both points addressed in the latest commit:

  • Relative overrides: the sh installer resolves JAWK_DATA_DIR/JAWK_INSTALL_DIR through cd ... && pwd after creating them, and the PowerShell installer roots a relative JAWK_INSTALL_DIR against the current location, so the launcher and the user PATH entry always carry absolute paths. Verified by installing with JAWK_DATA_DIR=.jawk/JAWK_INSTALL_DIR=bin (and JAWK_INSTALL_DIR=JawkRel on Windows) and running the launcher from a different working directory.
  • Behavior changes: the one-command installation is now recorded as an Unreleased bullet in behavior-changes.md, describing the previous manual download workflow and linking One-command installation of the jawk CLI executable #583.

@codex please review again

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6c4f13632c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/site/resources/get.ps1 Outdated
:try_java
if not exist "%~1" exit /b 0
"%~1" -version >nul 2>&1 || exit /b 0
"%~1" -version 2>&1 | findstr /r /c:"version .1\.[0-7]\." >nul && exit /b 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject legacy Java in the parent batch context

When JAWK_JAVA_HOME or JAVA_HOME points to Java 7 or older, this pipeline detects the legacy version, but exit /b 0 executes on the pipe's separate right-hand cmd context; the parent :try_java subroutine therefore continues to line 123 and selects the unsupported runtime instead of trying the next candidate. Microsoft's exit documentation specifies that /b exits the current batch context. Fresh evidence in this revision is that the newly added version check places that exit inside the pipeline rather than branching on findstr's status in the parent context.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6c4f13632c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/site/resources/get.ps1 Outdated
$installDir = if ($env:JAWK_INSTALL_DIR) { $env:JAWK_INSTALL_DIR } else { Join-Path $env:LOCALAPPDATA 'Jawk' }
# A relative override must not leave a working-directory-dependent entry on
# the user PATH: resolve it against the current location.
if (-not [System.IO.Path]::IsPathRooted($installDir)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fully qualify drive-relative Windows install paths

When JAWK_INSTALL_DIR is a Windows drive-relative or root-relative path such as C:Jawk or \Jawk, IsPathRooted returns true even though the path is not fully qualified, so this branch skips normalization. The resulting user PATH entry still depends on the current directory for drive C or on the process's current drive and can stop locating jawk.cmd in a later terminal. Fresh evidence in the revised Windows normalization is its use of rootedness as a proxy for an absolute path; resolve all overrides to a fully qualified provider path instead.

Useful? React with 👍 / 👎.

- Both installers now distinguish a confirmed-missing checksum asset
  (HTTP 404: warn and skip verification) from transport or server
  errors, which abort instead of silently disabling verification. The
  PowerShell installer retries transient failures (Windows PowerShell
  can drop a reused connection) before giving up.
- The PowerShell installer body runs in a script block, so the
  advertised `irm ... | iex` invocation no longer leaks
  ErrorActionPreference or helper variables into the caller's session.
- Drive-relative and root-relative JAWK_INSTALL_DIR overrides (C:Jawk,
  \Jawk) are fully qualified with GetFullPath, aligning and restoring
  the process working directory around the call.
- The shim reads the findstr verdict through errorlevel in a separate
  statement instead of appending exit /b to the pipeline, removing any
  ambiguity about which cmd context executes the exit.

Refs #583

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bertysentry

Copy link
Copy Markdown
Contributor Author

All four remaining points addressed in the latest commit:

  • Checksum failures fail closed: both installers now treat only a confirmed HTTP 404 as "this release publishes no checksum" (warn and skip); transport and other server errors abort the installation. The sh installer reads curl's HTTP status (wget's exit code 8 approximates the missing-asset case); the PowerShell installer inspects the WebException response and retries transient response-less failures up to three times — during testing, Windows PowerShell 5.1 occasionally dropped a reused connection on the checksum request, which without the retry would abort every install.
  • Caller scope: the PowerShell installer body runs inside & { ... }, so irm ... | iex no longer changes $ErrorActionPreference or leaves helper variables in the user's session. Verified by invoking via iex and checking the preference and variables afterwards.
  • Drive-relative paths: JAWK_INSTALL_DIR is fully qualified with [IO.Path]::GetFullPath (process cwd aligned with the PowerShell location and restored), which handles relative, drive-relative (C:Jawk), and root-relative (\Jawk) forms.
  • Legacy-Java rejection: the shim now reads the findstr verdict via if not errorlevel 1 in a separate statement. For the record, the pipeline-appended exit /b did return from the subroutine correctly in testing on Windows 11 cmd (verified with stub JREs reporting 1.7 and 17), but the separated form is unambiguous, so restructured anyway. The stub matrix confirms 1.7 is rejected and 17 accepted, with fall-through to the next candidate.

@codex please review again

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

Unknown error
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ecc2258471

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/site/resources/get Outdated
wget -qO "$1" "${SUM_URL}" 2>/dev/null || _rc=$?
case "${_rc}" in
0) return 0 ;;
8) return 1 ;; # server error response: a missing asset with wget

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle non-404 wget failures as verification errors

When curl is unavailable and the checksum request receives a 403, 429, or 5xx response, wget returns 8 and this revised branch treats it as a missing checksum, causing the installer to warn and install the jar without verification. The GNU Wget exit-status documentation defines status 8 as “Server issued an error response,” not specifically a 404; fresh evidence after the earlier review is this new wget-specific mapping, which must distinguish an actual 404 from other HTTP failures to preserve the intended fail-closed behavior.

Useful? React with 👍 / 👎.

wget exit status 8 covers every HTTP error response, so a 403, 429, or
5xx on the checksum download would have been treated as "this release
publishes no checksum" and skipped verification. The wget branch now
captures --server-response output and only downgrades to the warning
when the response is an actual 404; every other failure aborts.

Refs #583

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bertysentry

Copy link
Copy Markdown
Contributor Author

Addressed in the latest commit: the wget branch captures --server-response output and only treats an actual HTTP/... 404 status as a missing checksum (warn and skip); any other failure — 403, 429, 5xx, or a transport error — aborts the installation. Verified the shipped fetch_checksum function against stub wget implementations simulating 200, 404, 403, and DNS-failure behaviors: only 404 downgrades to the warning.

@codex please review again

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: af307e5cac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

One-command installation of the jawk CLI executable

1 participant