fix(update): stop stash/restore from clobbering desktop source on managed clones (#38542)
The stash/restore cycle in the update path was observed to clobber freshly-pulled source files (apps/desktop/ deletion -> Vite '[UNRESOLVED_ENTRY] Cannot resolve entry module index.html'). On a managed clone the user never edits the source tree, so any 'dirty' state is pure git artifact (CRLF renormalization, npm lockfile churn, files left behind when a directory was deleted upstream such as apps/bootstrap-installer/). Stashing that and re-applying it after a pull is fragile and unnecessary. - hermes update (hermes_cli/main.py): on a non-fork (managed) clone, discard working-tree dirt via reset --hard HEAD + clean -fd instead of stash/apply. Forks keep the stash machinery so intentional edits survive. Also pin core.autocrlf=false on Windows so the dirt is never created (mirrors install.ps1 #38239). - install.sh: replace the update-path stash/restore dance with a hard reset to origin/<branch>; the installer is a managed-only entry point. - install.sh + install.ps1 desktop stage: prefer 'npm ci' (wipes and reinstalls node_modules from the lockfile) over bare 'npm install', which can report 'up to date' against a stale marker while node_modules is empty -- leaving tsc unresolved so 'npm run pack' fails. Tests: managed clone cleans instead of stashing; fork still stashes; existing stash tests force the stash path explicitly.
This commit is contained in:
@ -1093,50 +1093,24 @@ clone_repo() {
|
||||
log_info "Existing installation found, updating..."
|
||||
cd "$INSTALL_DIR"
|
||||
|
||||
local autostash_ref=""
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
local stash_name
|
||||
stash_name="hermes-install-autostash-$(date -u +%Y%m%d-%H%M%S)"
|
||||
log_info "Local changes detected, stashing before update..."
|
||||
git stash push --include-untracked -m "$stash_name"
|
||||
autostash_ref="stash@{0}"
|
||||
fi
|
||||
|
||||
# This is a managed clone the user never edits, so any working-tree
|
||||
# dirt is git artifact (CRLF renormalization, npm lockfile churn,
|
||||
# files left behind when a directory was deleted upstream such as
|
||||
# apps/bootstrap-installer/). The old path stashed that dirt and
|
||||
# re-applied it after the pull, but the stash/restore cycle has
|
||||
# clobbered freshly-pulled source files (apps/desktop/ →
|
||||
# "[UNRESOLVED_ENTRY] Cannot resolve entry module index.html").
|
||||
# Discard the dirt with a hard reset instead — mirrors install.ps1's
|
||||
# update path. Fork users customize via `hermes update`, which keeps
|
||||
# the stash machinery; the installer is a managed-only entry point.
|
||||
git fetch origin
|
||||
git checkout "$BRANCH"
|
||||
git pull --ff-only origin "$BRANCH"
|
||||
|
||||
if [ -n "$autostash_ref" ]; then
|
||||
local restore_now="yes"
|
||||
if [ -t 0 ] && [ -t 1 ]; then
|
||||
echo
|
||||
log_warn "Local changes were stashed before updating."
|
||||
log_warn "Restoring them may reapply local customizations onto the updated codebase."
|
||||
printf "Restore local changes now? [Y/n] "
|
||||
read -r restore_answer
|
||||
case "$restore_answer" in
|
||||
""|y|Y|yes|YES|Yes) restore_now="yes" ;;
|
||||
*) restore_now="no" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ "$restore_now" = "yes" ]; then
|
||||
log_info "Restoring local changes..."
|
||||
if git stash apply "$autostash_ref"; then
|
||||
git stash drop "$autostash_ref" >/dev/null
|
||||
log_warn "Local changes were restored on top of the updated codebase."
|
||||
log_warn "Review git diff / git status if Hermes behaves unexpectedly."
|
||||
else
|
||||
log_error "Update succeeded, but restoring local changes failed. Your changes are still preserved in git stash."
|
||||
log_info "Resolve manually with: git stash apply $autostash_ref"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log_info "Skipped restoring local changes."
|
||||
log_info "Your changes are still preserved in git stash."
|
||||
log_info "Restore manually with: git stash apply $autostash_ref"
|
||||
fi
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
log_info "Discarding working-tree changes on managed clone before update..."
|
||||
git reset --hard HEAD >/dev/null 2>&1 || true
|
||||
git clean -fd >/dev/null 2>&1 || true
|
||||
fi
|
||||
git checkout "$BRANCH"
|
||||
git reset --hard "origin/$BRANCH"
|
||||
else
|
||||
log_error "Directory exists but is not a git repository: $INSTALL_DIR"
|
||||
log_info "Remove it or choose a different directory with --dir"
|
||||
@ -2271,8 +2245,16 @@ install_desktop() {
|
||||
# 1. Root workspace install so apps/desktop's deps (Electron, Vite,
|
||||
# node-pty prebuilds) resolve. The browser-tools install runs in the
|
||||
# repo-root package workspace, which does not pull apps/* deps.
|
||||
#
|
||||
# Prefer `npm ci`: it deletes node_modules and reinstalls from the
|
||||
# lockfile, so it always produces a complete tree. Bare `npm install`
|
||||
# can report "up to date" against a stale node_modules/.package-lock.json
|
||||
# marker while node_modules is actually empty (Windows workspace-hoisting
|
||||
# flake) — leaving tsc/typescript unresolved and `npm run pack`'s
|
||||
# `tsc -b` failing with no obvious cause. Fall back to `npm install`
|
||||
# only if `npm ci` is unavailable or the lockfile is out of sync.
|
||||
log_info "Installing desktop workspace dependencies (includes Electron ~150MB, 1-3min)..."
|
||||
( cd "$INSTALL_DIR" && npm install ) || {
|
||||
( cd "$INSTALL_DIR" && npm ci ) || ( cd "$INSTALL_DIR" && npm install ) || {
|
||||
log_error "Desktop workspace npm install failed"
|
||||
return 1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user