Skip to content

Commit 48158c4

Browse files
committed
chore: wip
1 parent e37525d commit 48158c4

File tree

3 files changed

+120
-121
lines changed

3 files changed

+120
-121
lines changed

packages/launchpad/src/dev/dump.ts

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -693,9 +693,11 @@ export async function dump(dir: string, options: DumpOptions = {}): Promise<void
693693
sniffResult = { pkgs: [], env: {} }
694694
}
695695

696-
// Ensure project php.ini and Laravel post-setup run at least once per project (fast path)
697-
await ensureProjectPhpIni(projectDir, envDir)
698-
await maybeRunLaravelPostSetup(projectDir, envDir, isShellIntegration)
696+
// In shell integration fast path, skip services and heavy post-setup
697+
// Only ensure php.ini exists if already marked ready
698+
if (fs.existsSync(path.join(envDir, '.launchpad_ready'))) {
699+
await ensureProjectPhpIni(projectDir, envDir)
700+
}
699701

700702
outputShellCode(
701703
dir,
@@ -841,13 +843,7 @@ export async function dump(dir: string, options: DumpOptions = {}): Promise<void
841843
const globalBinPath = path.join(globalEnvDir, 'bin')
842844
const globalSbinPath = path.join(globalEnvDir, 'sbin')
843845

844-
// Auto-start services even when no packages need installation
845-
try {
846-
await setupProjectServices(projectDir, sniffResult, !effectiveQuiet)
847-
}
848-
catch (error) {
849-
console.error(`⚠️ Service auto-start failed: ${error instanceof Error ? error.message : String(error)}`)
850-
}
846+
// In shell integration, do not start services automatically
851847

852848
outputShellCode(dir, envBinPath, envSbinPath, projectHash, sniffResult, globalBinPath, globalSbinPath)
853849
return
@@ -883,17 +879,10 @@ export async function dump(dir: string, options: DumpOptions = {}): Promise<void
883879
}
884880
await createPhpShimsAfterInstall(envDir)
885881

886-
// Auto-start services for shell integration too
887-
try {
888-
await setupProjectServices(projectDir, sniffResult, !effectiveQuiet)
889-
}
890-
catch (error) {
891-
console.error(`⚠️ Service auto-start failed: ${error instanceof Error ? error.message : String(error)}`)
892-
}
882+
// Do not auto-start services during shell integration
893883

894-
// Ensure project php.ini and Laravel post-setup run at least once per project (install path)
884+
// Ensure project php.ini exists only
895885
await ensureProjectPhpIni(projectDir, envDir)
896-
await maybeRunLaravelPostSetup(projectDir, envDir, isShellIntegration)
897886

898887
outputShellCode(dir, envBinPath, envSbinPath, projectHash, sniffResult, globalBinPath, globalSbinPath)
899888
return
@@ -910,7 +899,7 @@ export async function dump(dir: string, options: DumpOptions = {}): Promise<void
910899
catch {}
911900
}
912901

913-
// Auto-start services for any project that has services configuration
902+
// Auto-start services for any project that has services configuration (non-shell calls only)
914903
// Pre-activation hook (runs after install/services and before shell activation)
915904
const preActivation = config.preActivation
916905
if (dependencyFile) {
@@ -929,17 +918,21 @@ export async function dump(dir: string, options: DumpOptions = {}): Promise<void
929918
}
930919
}
931920
// Suppress interstitial processing messages during service startup phase
932-
const prevProcessing = process.env.LAUNCHPAD_PROCESSING
933-
process.env.LAUNCHPAD_PROCESSING = '0'
934-
await setupProjectServices(projectDir, sniffResult, !effectiveQuiet)
935-
if (prevProcessing === undefined)
936-
delete process.env.LAUNCHPAD_PROCESSING
937-
else
938-
process.env.LAUNCHPAD_PROCESSING = prevProcessing
921+
if (!isShellIntegration) {
922+
const prevProcessing = process.env.LAUNCHPAD_PROCESSING
923+
process.env.LAUNCHPAD_PROCESSING = '0'
924+
await setupProjectServices(projectDir, sniffResult, !effectiveQuiet)
925+
if (prevProcessing === undefined)
926+
delete process.env.LAUNCHPAD_PROCESSING
927+
else
928+
process.env.LAUNCHPAD_PROCESSING = prevProcessing
929+
}
939930

940931
// Ensure php.ini and Laravel post-setup runs (regular path)
941932
await ensureProjectPhpIni(projectDir, envDir)
942-
await maybeRunLaravelPostSetup(projectDir, envDir, isShellIntegration)
933+
if (!isShellIntegration) {
934+
await maybeRunLaravelPostSetup(projectDir, envDir, isShellIntegration)
935+
}
943936

944937
// Mark environment as ready for fast shell activation on subsequent prompts
945938
try {

packages/launchpad/src/dev/shellcode.ts

Lines changed: 95 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,18 @@ __launchpad_update_path() {
159159
__launchpad_update_library_paths_fast() {
160160
local env_dir="$1"
161161
162+
# Prevent zsh nomatch warnings inside this function (restores on return)
163+
if [[ -n "$ZSH_VERSION" ]]; then
164+
setopt localoptions nonomatch
165+
fi
166+
162167
if [[ ! -d "$env_dir" ]]; then
168+
# nothing to do
163169
return 0
164170
fi
165171
166172
# Build library paths from direct lib directories only (fast path)
167173
local lib_paths=""
168-
169-
# Add direct lib directories only
170174
for lib_dir in "$env_dir/lib" "$env_dir/lib64"; do
171175
if [[ -d "$lib_dir" ]]; then
172176
if [[ -z "$lib_paths" ]]; then
@@ -177,52 +181,6 @@ __launchpad_update_library_paths_fast() {
177181
fi
178182
done
179183
180-
# Add package-specific library directories with validation
181-
# Only include packages with actual working libraries
182-
# Prioritize source-built packages over pre-built binaries
183-
if [[ -d "$env_dir" ]]; then
184-
# First pass: Add source-built packages (like our PHP) with priority
185-
for domain_dir in "$env_dir"/*.org "$env_dir"/*.net "$env_dir"/*.com "$env_dir"/*.sh "$env_dir"/*.io; do
186-
if [[ -d "$domain_dir" ]]; then
187-
local domain_name=$(basename "$domain_dir")
188-
189-
# Find version directories and validate they have proper libraries
190-
for version_dir in "$domain_dir"/v*; do
191-
if [[ -d "$version_dir" ]]; then
192-
for lib_subdir in "$version_dir/lib" "$version_dir/lib64"; do
193-
if [[ -d "$lib_subdir" ]]; then
194-
# Validate that this lib directory has actual library files
195-
# Skip if it only contains broken/placeholder files
196-
local has_valid_libs=false
197-
198-
# Check for common library patterns that indicate a working installation
199-
if [[ -n "$(find "$lib_subdir" -name "*.dylib" -size +100c 2>/dev/null | head -1)" ]] || \
200-
[[ -n "$(find "$lib_subdir" -name "*.so*" -size +100c 2>/dev/null | head -1)" ]] || \
201-
[[ -n "$(find "$lib_subdir" -name "*.a" -size +100c 2>/dev/null | head -1)" ]]; then
202-
has_valid_libs=true
203-
fi
204-
205-
# Special case: If this is a source-built package (like our PHP), always include it
206-
if [[ "$domain_name" == "php.net" ]] && [[ -f "$version_dir/bin/php" ]]; then
207-
has_valid_libs=true
208-
fi
209-
210-
# Add to library paths if it has valid libraries
211-
if [[ "$has_valid_libs" == "true" ]]; then
212-
if [[ -z "$lib_paths" ]]; then
213-
lib_paths="$lib_subdir"
214-
else
215-
lib_paths="$lib_paths:$lib_subdir"
216-
fi
217-
fi
218-
fi
219-
done
220-
fi
221-
done
222-
fi
223-
done
224-
fi
225-
226184
# Set up library path environment variables if we have paths
227185
if [[ -n "$lib_paths" ]]; then
228186
# Store original values if not already stored
@@ -641,53 +599,110 @@ __launchpad_chpwd() {
641599
return 0
642600
fi
643601
602+
# Avoid zsh glob nomatch errors inside this handler
603+
if [[ -n "$ZSH_VERSION" ]]; then
604+
setopt localoptions nonomatch
605+
fi
606+
644607
# Ultra-fast activation: compute environment path and check if ready
645-
local project_hash
646-
project_hash=$(echo -n "$project_dir" | sha256sum 2>/dev/null | cut -d' ' -f1 | cut -c1-8) || project_hash="default"
608+
# Resolve to physical path and compute MD5 (matches generateProjectHash in dump.ts)
609+
local real_project_dir
610+
real_project_dir=$(cd "$project_dir" 2>/dev/null && pwd -P || echo "$project_dir")
611+
local project_basename
612+
project_basename=$(basename "$real_project_dir")
613+
local md5hash
614+
if command -v md5 >/dev/null 2>&1; then
615+
md5hash=$(md5 -q -s "$real_project_dir" 2>/dev/null || md5 -q "$real_project_dir" 2>/dev/null)
616+
fi
617+
if [[ -z "$md5hash" ]] && command -v md5sum >/dev/null 2>&1; then
618+
md5hash=$(printf "%s" "$real_project_dir" | md5sum 2>/dev/null | awk '{print $1}')
619+
fi
620+
if [[ -z "$md5hash" ]] && command -v openssl >/dev/null 2>&1; then
621+
md5hash=$(printf "%s" "$real_project_dir" | openssl md5 2>/dev/null | awk '{print $2}')
622+
fi
623+
if [[ -z "$md5hash" ]]; then
624+
md5hash="00000000"
625+
fi
626+
local project_hash="\${project_basename}_$(echo "$md5hash" | cut -c1-8)"
647627
local env_dir="$HOME/.local/share/launchpad/envs/$project_hash"
648628
649-
# Check persistent cache first (instant activation)
650-
local cache_file="$__launchpad_persistent_cache_dir/env_cache_$(echo -n "$env_dir" | sha256sum 2>/dev/null | cut -d' ' -f1 | cut -c1-16)"
629+
# Fallback: if md5-based env dir doesn't exist, try to locate legacy env by basename prefix
630+
if [[ ! -d "$env_dir/bin" ]]; then
631+
local envs_root="$HOME/.local/share/launchpad/envs"
632+
if [[ -d "$envs_root" ]]; then
633+
local found_env=""
634+
# Iterate safely (no globs) and match prefix
635+
for candidate in "$envs_root"/*; do
636+
if [[ -d "$candidate" ]]; then
637+
local base=$(basename "$candidate")
638+
case "$base" in
639+
"\${project_basename}_"*)
640+
if [[ -d "$candidate/bin" ]]; then
641+
found_env="$candidate"
642+
# Prefer one that has .launchpad_ready
643+
if [[ -f "$candidate/.launchpad_ready" ]]; then
644+
env_dir="$candidate"
645+
break
646+
fi
647+
fi
648+
;;
649+
esac
650+
fi
651+
done
652+
if [[ -z "$env_dir" || ! -d "$env_dir/bin" ]]; then
653+
if [[ -n "$found_env" ]]; then
654+
env_dir="$found_env"
655+
fi
656+
fi
657+
fi
658+
fi
659+
660+
# Persistent cache: check before slow operations
661+
local cache_file="$__launchpad_persistent_cache_dir/env_cache_$(printf "%s" "$env_dir" | md5sum 2>/dev/null | awk '{print $1}' | cut -c1-16)"
651662
local current_time=$(date +%s)
652663
local cache_duration=1800 # 30 minutes for shell integration
653-
654-
# Use longer cache durations for test environments
664+
# Use longer cache durations for test/development environments
655665
if [[ "$project_dir" == *"test"* || "$project_dir" == *"launchpad"* || "$NODE_ENV" == "test" ]]; then
656666
cache_duration=3600 # 1 hour for test and development environments
657667
fi
658-
659668
if [[ -f "$cache_file" ]]; then
660669
local cache_file_time=$(stat -c %Y "$cache_file" 2>/dev/null || stat -f %m "$cache_file" 2>/dev/null || echo 0)
661670
if [[ $((current_time - cache_file_time)) -lt $cache_duration && -d "$env_dir/bin" ]]; then
662-
# Instant activation from persistent cache
671+
# Instant activation from persistent cache (no filesystem scans)
663672
export PATH="$env_dir/bin:$LAUNCHPAD_ORIGINAL_PATH"
664673
__launchpad_update_library_paths_fast "$env_dir"
665674
__launchpad_ensure_global_path_fast
666675
__launchpad_ensure_system_path
667676
hash -r 2>/dev/null || true
668-
669-
if [[ "\$\{LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}\}" != "false" ]]; then
670-
printf "${activationMessage}\\n" >&2
677+
if [[ "\${LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}}" != "false" ]]; then
678+
printf "${activationMessage}\n" >&2
671679
fi
672680
return 0
673681
fi
674682
fi
675683
684+
# Check readiness markers explicitly (used by tests and fast path)
685+
if [[ -d "$env_dir/pkgs" || -f "$env_dir/.launchpad_ready" ]]; then
686+
__lp_markers_ready=1
687+
else
688+
__lp_markers_ready=0
689+
fi
690+
676691
# If environment exists and has binaries, activate quickly
677692
# use glob expansion which is faster than ls
678-
if [[ -d "$env_dir/bin" ]] && [[ -n $(echo "$env_dir/bin"/*) && $(echo "$env_dir/bin"/*) != "$env_dir/bin/*" ]] && [[ -d "$env_dir/pkgs" || -f "$env_dir/.launchpad_ready" ]]; then
693+
if [[ -d "$env_dir/bin" ]] && [[ $__lp_markers_ready -eq 1 || $(echo "$env_dir/bin"/*) != "$env_dir/bin/*" ]]; then
679694
export PATH="$env_dir/bin:$LAUNCHPAD_ORIGINAL_PATH"
680695
__launchpad_update_library_paths_fast "$env_dir"
681696
__launchpad_ensure_global_path_fast
682697
__launchpad_ensure_system_path
683698
hash -r 2>/dev/null || true
684699
685-
# Update persistent cache
686-
mkdir -p "$(dirname "$cache_file")" 2>/dev/null
687-
touch "$cache_file" 2>/dev/null
700+
# Update persistent cache for instant future activation
701+
mkdir -p "$(dirname "$cache_file")" 2>/dev/null || true
702+
touch "$cache_file" 2>/dev/null || true
688703
689-
if [[ "\$\{LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}\}" != "false" ]]; then
690-
printf "${activationMessage}\\n" >&2
704+
if [[ "\${LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}}" != "false" ]]; then
705+
printf "${activationMessage}\n" >&2
691706
fi
692707
return 0
693708
fi
@@ -696,11 +711,7 @@ __launchpad_chpwd() {
696711
697712
# Mark setup as in progress
698713
__launchpad_setup_in_progress="$project_dir"
699-
700-
# Show immediate feedback
701-
if [[ "\$\{LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}\}" != "false" ]]; then
702-
printf "🔧 Setting up environment for \\033[3m$(basename "$project_dir")\\033[0m...\\r" >&2
703-
fi
714+
# Suppress transient progress to keep prompt responsive; only final activation prints
704715
705716
# Optimize environment setup with shorter timeout and shell-only mode
706717
local env_output
@@ -709,17 +720,11 @@ __launchpad_chpwd() {
709720
# Ensure global dependencies are available first
710721
__launchpad_setup_global_deps
711722
712-
# Run environment setup without timeout - let it take as long as needed
723+
# Run environment setup without timeout - let it take as long as needed
713724
local temp_file=$(mktemp)
714725
715-
# Run with real-time progress display - show progress on stderr, capture shell code on stdout
716-
if [[ "\$\{LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}\}" != "false" ]]; then
717-
# Show progress in real-time while capturing output
718-
${launchpadBinary} dev "$project_dir" --shell > "$temp_file"
719-
else
720-
# Quiet mode - suppress all output
721-
${launchpadBinary} dev "$project_dir" --shell --quiet > "$temp_file" 2>/dev/null
722-
fi
726+
# Always run shell-mode setup quietly for speed; capture only the shell code
727+
${launchpadBinary} dev "$project_dir" --shell --quiet > "$temp_file" 2>/dev/null
723728
setup_exit_code=$?
724729
725730
# Extract shell code from output
@@ -731,7 +736,7 @@ __launchpad_chpwd() {
731736
732737
if [[ $setup_exit_code -eq 130 ]]; then
733738
# User interrupted with Ctrl+C
734-
if [[ "\$\{LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}\}" != "false" ]]; then
739+
if [[ "\${LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}}" != "false" ]]; then
735740
printf "\\r\\033[K⚠️ Environment setup cancelled\\n" >&2
736741
fi
737742
return 130
@@ -753,11 +758,14 @@ __launchpad_chpwd() {
753758
# Clear command hash table to ensure commands are found in new PATH
754759
hash -r 2>/dev/null || true
755760
756-
# Create persistent cache file for instant future activation
757-
touch "$cache_file" 2>/dev/null
761+
# Mark environment ready for instant future activation (both cache and marker)
762+
mkdir -p "$env_dir" 2>/dev/null || true
763+
touch "$env_dir/.launchpad_ready" 2>/dev/null || true
764+
mkdir -p "$(dirname "$cache_file")" 2>/dev/null || true
765+
touch "$cache_file" 2>/dev/null || true
758766
759767
# Show clean activation message
760-
if [[ "\$\{LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}\}" != "false" ]]; then
768+
if [[ "\${LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}}" != "false" ]]; then
761769
printf "\\r\\033[K${activationMessage}\\n" >&2
762770
fi
763771
else
@@ -769,12 +777,12 @@ __launchpad_chpwd() {
769777
__launchpad_ensure_system_path
770778
hash -r 2>/dev/null || true
771779
772-
if [[ "\$\{LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}\}" != "false" ]]; then
780+
if [[ "\${LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}}" != "false" ]]; then
773781
printf "\\r\\033[K${activationMessage}\\n" >&2
774782
fi
775783
else
776784
# Clear any progress message on failure
777-
if [[ "\$\{LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}\}" != "false" ]]; then
785+
if [[ "\${LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}}" != "false" ]]; then
778786
printf "\\r\\033[K" >&2
779787
fi
780788
fi
@@ -817,7 +825,7 @@ __launchpad_chpwd() {
817825
unset LAUNCHPAD_ORIGINAL_LD_LIBRARY_PATH
818826
819827
# Show deactivation message
820-
if [[ "\$\{LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}\}" != "false" ]]; then
828+
if [[ "\${LAUNCHPAD_SHOW_ENV_MESSAGES:-${showMessages}}" != "false" ]]; then
821829
printf "${deactivationMessage}\\n" >&2
822830
fi
823831
@@ -916,9 +924,7 @@ __launchpad_source_hooks_dir() {
916924
fi
917925
}
918926
919-
# One-time setup on shell initialization
920-
__launchpad_setup_global_deps
921-
__launchpad_ensure_global_path_fast
927+
# One-time setup on shell initialization (no global setup)
922928
__launchpad_source_hooks_dir "$HOME/.config/launchpad/hooks/init.d"
923929
924930
# Clear command hash table on initial load

0 commit comments

Comments
 (0)