Update install script for home-directory defaults#341
Conversation
Reviewer's GuideInstaller now defaults to installing lets into $HOME/.lets/bin via a Bash-based script, adds LETS_HOME/LETS_VERSION support plus PATH/symlink/profile management, blocks unsafe legacy /usr/local/bin installs, and aligns docs, dev workflow, and changelog with the new layout. Sequence diagram for the updated installer and PATH/profile behaviorsequenceDiagram
actor User
participant Shell
participant Installer as install_sh
participant GitHub as GitHub_releases
participant FS as Filesystem
User->>Shell: curl -fsSL ... | bash
Shell->>Installer: execute script
Installer->>Installer: parse_args
Installer->>Installer: resolve TAG
Note over Installer: LETS_VERSION overrides positional tag
Installer->>Installer: check_old_usr_local_install
Installer->>FS: check /usr/local/bin/lets
alt Homebrew-managed lets
Installer-->>User: log_info Homebrew install detected
else legacy non-Homebrew lets
Installer-->>User: log_crit remove old /usr/local/bin/lets
Installer-->>Shell: exit 1
Installer-->>Shell: return
end
Installer->>Installer: get_binaries
Installer->>Installer: tag_to_version
Installer->>Installer: uname_os / uname_arch
Installer->>GitHub: download tarball and checksum
GitHub-->>Installer: tarball and checksum
Installer->>Installer: hash_sha256_verify
Installer->>FS: untar and install to $HOME/.lets/bin
Installer-->>User: log_info installed $HOME/.lets/bin/lets
Installer->>Installer: update_shell_profile
Installer->>Installer: try_symlink_in_path
loop preferred_dirs
Installer->>FS: ensure dir exists
Installer->>FS: ln -sf BIN_DIR/lets -> dir/lets
alt symlink_created
Installer-->>User: log_info created symlink
Note over Installer: break
end
end
alt symlink_created_in_preferred_dir
Installer-->>User: lets available via existing PATH entry
else no_preferred_dir_in_PATH
Installer->>FS: mkdir -p $HOME/.local/bin
Installer->>FS: ln -sf BIN_DIR/lets -> $HOME/.local/bin/lets
Installer->>Installer: detect shell and profile file
alt ~/.local/bin already in PATH
Installer-->>User: log_info existing PATH config
Installer-->>User: print one-shot PATH export
else not yet configured
alt interactive_shell
Installer-->>User: prompt to add ~/.local/bin to PATH
User-->>Installer: answer y/n
alt user_accepts
Installer->>FS: append PATH export to shell_profile
Installer-->>User: log_info PATH updated
else user_declines
Installer-->>User: log_info skipped profile change
end
else non_interactive
Installer->>FS: append PATH export to shell_profile
Installer-->>User: log_info PATH updated
end
end
end
Installer-->>Shell: exit 0
Shell-->>User: lets command ready in PATH
Flow diagram for PATH, symlink, and profile management in the installerflowchart TD
A[start update_shell_profile] --> B[try_symlink_in_path lets]
B -->|symlink_created_in_existing_preferred_dir| Z[finish update_shell_profile]
B -->|no_symlink_created| C[ensure $HOME/.local/bin exists]
C --> D[create symlink $HOME/.local/bin/lets -> BIN_DIR/lets]
D -->|success| E[detect shell and OS]
D -->|failure| D1[log_err and print manual PATH instructions]
D1 --> Z
E --> F{shell type}
F -->|zsh| G[set shell_profile=$HOME/.zshrc
set path_export=export PATH='$HOME/.local/bin:$PATH']
F -->|bash_on_Darwin| H[prefer .bash_profile then .bashrc
set path_export]
F -->|bash_other_OS| I[prefer .bashrc then .bash_profile
set path_export]
F -->|fish| J[set shell_profile=$HOME/.config/fish/config.fish
set path_export=fish_add_path '$HOME/.local/bin']
F -->|other| K[log_err unknown shell
print manual PATH instructions]
K --> Z
G --> L[continue with chosen shell_profile]
H --> L
I --> L
J --> L
L --> M{shell_profile already adds .local/bin?}
M -->|yes| N[log_info PATH already configured
print one-shot PATH export]
N --> Z
M -->|no| O{stdin is interactive?}
O -->|no| P[append PATH export block to shell_profile]
P --> Q[log_info PATH updated and print one-shot export]
Q --> Z
O -->|yes| R[prompt user: add ~/.local/bin to PATH?]
R -->|user_yes| S[create shell_profile if missing
append PATH export block]
S --> Q
R -->|user_no| T[log_info skipped profile change
print manual PATH instructions]
T --> Z
Z[end update_shell_profile]
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- The new interactive prompt in
update_shell_profile(read -r -p ...) will block non-interactive/CI installs; consider adding a flag or environment variable to force non-interactive behavior and skip prompts safely. - The
dir_in_pathhelper uses a simplegrepon:$PATH:which can still mis-detect directories with shared prefixes (e.g./home/user/binvs/home/user/bin-extra); consider normalizing the paths and comparing components explicitly. - In
update_shell_profile, the logic for detecting whether~/.local/binis already onPATHis regex-based and shell-specific; factoring this into a small, testable helper (reused fordir_in_path) would reduce duplication and make edge-case handling clearer.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The new interactive prompt in `update_shell_profile` (`read -r -p ...`) will block non-interactive/CI installs; consider adding a flag or environment variable to force non-interactive behavior and skip prompts safely.
- The `dir_in_path` helper uses a simple `grep` on `:$PATH:` which can still mis-detect directories with shared prefixes (e.g. `/home/user/bin` vs `/home/user/bin-extra`); consider normalizing the paths and comparing components explicitly.
- In `update_shell_profile`, the logic for detecting whether `~/.local/bin` is already on `PATH` is regex-based and shell-specific; factoring this into a small, testable helper (reused for `dir_in_path`) would reduce duplication and make edge-case handling clearer.
## Individual Comments
### Comment 1
<location path="install.sh" line_range="212-219" />
<code_context>
+ log_crit "then run this installer again"
+ exit 1
+}
+dir_in_path() {
+ check_dir=$1
+
+ if [ -d "$check_dir" ]; then
+ check_dir=$(cd "$check_dir" >/dev/null 2>&1 && pwd) || return 1
+ fi
+
+ echo ":$PATH:" | grep -q ":$check_dir:"
+}
+try_symlink_in_path() {
</code_context>
<issue_to_address>
**issue (bug_risk):** Use fixed-string grep to avoid regex matching issues when checking if a directory is in PATH.
Without `-F`, characters like `.` in `$check_dir` are interpreted as regex, so `/home/user/.local/bin` could incorrectly match `/home/userXlocal/bin`. Using fixed-string grep makes the PATH check accurate, e.g.:
```bash
echo ":$PATH:" | grep -F -q ":$check_dir:"
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| dir_in_path() { | ||
| check_dir=$1 | ||
|
|
||
| if [ -d "$check_dir" ]; then | ||
| check_dir=$(cd "$check_dir" >/dev/null 2>&1 && pwd) || return 1 | ||
| fi | ||
|
|
||
| echo ":$PATH:" | grep -q ":$check_dir:" |
There was a problem hiding this comment.
issue (bug_risk): Use fixed-string grep to avoid regex matching issues when checking if a directory is in PATH.
Without -F, characters like . in $check_dir are interpreted as regex, so /home/user/.local/bin could incorrectly match /home/userXlocal/bin. Using fixed-string grep makes the PATH check accurate, e.g.:
echo ":$PATH:" | grep -F -q ":$check_dir:"
Summary
$HOME/.lets/binand switch the script to Bash.LETS_VERSIONprecedence, and preserve Amp-style PATH symlink/profile handling.Testing
bash -n install.shLETS_VERSIONprecedence.lets fmtgo test ./...lets buildSummary by Sourcery
Update the installer to use a home-directory–scoped layout by default and align documentation, development workflow, and changelog with the new installation behavior.
New Features:
Bug Fixes:
Enhancements:
Documentation: