Skip to content

fix: add Windows Git Bash fallbacks for uname, date, and cat#11

Open
sampurnamo wants to merge 1 commit intoConaryLabs:mainfrom
sampurnamo:fix/windows-shell-fallbacks-clean
Open

fix: add Windows Git Bash fallbacks for uname, date, and cat#11
sampurnamo wants to merge 1 commit intoConaryLabs:mainfrom
sampurnamo:fix/windows-shell-fallbacks-clean

Conversation

@sampurnamo
Copy link
Contributor

Summary

In restricted shell contexts on Windows (Git Bash running within hook processes), core POSIX utilities like uname, date, and cat may not be available in $PATH. This causes the mira-wrapper to fail with errors like:

line 47: date: command not found

This PR guards all shell utility calls with 2>/dev/null fallbacks:

  • uname -s: Falls back to "Windows" — safe default that triggers Windows code paths
  • uname -m: Falls back to "x86_64" — most common Windows architecture
  • date +%s: Falls back to the file mtime being compared — produces cache_age=0, which means "cache is fresh" (safe: skips unnecessary update checks)
  • cat: Falls back to "" — triggers re-download path (safe)
  • Windows* pattern added to all case statements that lacked it

Test plan

  • Verify wrapper still works on Linux/macOS (uname available — fallbacks never trigger)
  • Verify wrapper works in Windows Git Bash with full PATH
  • Verify wrapper works in restricted Windows hook contexts (stripped PATH)
  • Confirm install_jq() handles Windows detection correctly

Replaces #10 (which had merge conflicts from fork divergence).

In restricted shell contexts on Windows (Git Bash within hooks),
core utilities like uname, date, and cat may not be in PATH.

Changes:
- Guard all uname -s calls with 2>/dev/null || echo "Windows"
- Guard all uname -m calls with 2>/dev/null || echo "x86_64"
- Guard all date +%s calls with 2>/dev/null fallback to mtime
- Guard all cat calls with 2>/dev/null || echo "" fallback
- Add Windows* pattern to all OS case statements
- Add x86_64 default for architecture detection
@TusanHomichi
Copy link
Contributor

Code review

Found 1 issue:

  1. date +%s fallback produces zero age, defeating both the cache TTL check and stale lock cleanup. When date +%s fails, the fallback substitutes the mtime value itself (echo "$file_mtime" / echo "$lock_mtime"), making the arithmetic (mtime - mtime) = 0. This means:

    • cache_age=0 always passes the freshness check (0 < 86400), so update checks are permanently skipped
    • lock_age=0 never satisfies lock_age > 60, so stale locks are never reclaimed (potential deadlock after crash)

    The correct fallback is echo 0 (Unix epoch), which produces a very large age and forces the safe path (re-check updates / clean up stale locks):

    cache_age=$(( $(date +%s 2>/dev/null || echo 0) - file_mtime ))
    local lock_age=$(( $(date +%s 2>/dev/null || echo 0) - lock_mtime ))

    # Accept any installed version if update cache is fresh
    if [ -f "$UPDATE_CACHE" ]; then
    file_mtime=$(stat -c %Y "$UPDATE_CACHE" 2>/dev/null || stat -f %m "$UPDATE_CACHE" 2>/dev/null || date -r "$UPDATE_CACHE" +%s 2>/dev/null || echo 0)
    cache_age=$(( $(date +%s 2>/dev/null || echo "$file_mtime") - file_mtime ))
    if [ "$cache_age" -lt "$CACHE_TTL" ]; then
    exec "$MIRA_BIN" "$@"
    fi

    if ! mkdir "$lockdir" 2>/dev/null; then
    local lock_mtime
    lock_mtime=$(stat -c %Y "$lockdir" 2>/dev/null || stat -f %m "$lockdir" 2>/dev/null || echo 0)
    local lock_age=$(( $(date +%s 2>/dev/null || echo "$lock_mtime") - lock_mtime ))
    if [ "$lock_age" -gt 60 ]; then
    rmdir "$lockdir" 2>/dev/null || true
    mkdir "$lockdir" 2>/dev/null || return
    else
    return # Another process is writing -- skip

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

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.

2 participants