@@ -176,12 +176,55 @@ __launchpad_switch_environment() {
176
176
printf "⏱️ [0ms] Shell integration started for PWD=%s\\n" "$PWD" >&2
177
177
fi
178
178
179
+ # Known dependency filenames (keep in sync with DEPENDENCY_FILE_NAMES in src/env.ts)
180
+ local _dep_names=(
181
+ # Launchpad-specific files (highest priority)
182
+ "dependencies.yaml" "dependencies.yml" "deps.yaml" "deps.yml" "pkgx.yaml" "pkgx.yml" "launchpad.yaml" "launchpad.yml"
183
+ # Node.js/JavaScript
184
+ "package.json"
185
+ # Python
186
+ "pyproject.toml" "requirements.txt" "setup.py" "Pipfile" "Pipfile.lock"
187
+ # Rust
188
+ "Cargo.toml"
189
+ # Go
190
+ "go.mod" "go.sum"
191
+ # Ruby
192
+ "Gemfile"
193
+ # Deno
194
+ "deno.json" "deno.jsonc"
195
+ # GitHub Actions
196
+ "action.yml" "action.yaml"
197
+ # Kubernetes/Docker
198
+ "skaffold.yaml" "skaffold.yml"
199
+ # Version control files
200
+ ".nvmrc" ".node-version" ".ruby-version" ".python-version" ".terraform-version"
201
+ # Package manager files
202
+ "yarn.lock" "bun.lockb" ".yarnrc"
203
+ )
204
+
179
205
# Step 1: Find project directory using our fast binary (no artificial timeout)
180
206
local project_dir=""
181
207
if ${ launchpadBinary } dev:find-project-root "$PWD" >/dev/null 2>&1; then
182
208
project_dir=$(LAUNCHPAD_DISABLE_SHELL_INTEGRATION=1 ${ launchpadBinary } dev:find-project-root "$PWD" 2>/dev/null || echo "")
183
209
fi
184
210
211
+ # Fallback: If binary didn't detect a project, scan upwards for known dependency files
212
+ if [[ -z "$project_dir" ]]; then
213
+ local __dir="$PWD"
214
+ while [[ "$__dir" != "/" ]]; do
215
+ for name in "\${_dep_names[@]}"; do
216
+ if [[ -f "$__dir/$name" ]]; then
217
+ project_dir="$__dir"
218
+ break
219
+ fi
220
+ done
221
+ if [[ -n "$project_dir" ]]; then
222
+ break
223
+ fi
224
+ __dir="$(dirname "$__dir")"
225
+ done
226
+ fi
227
+
185
228
# Verbose: show project detection result
186
229
if [[ "$verbose_mode" == "true" && "$__lp_should_verbose_print" == "1" ]]; then
187
230
if [[ -n "$project_dir" ]]; then
@@ -270,22 +313,28 @@ __launchpad_switch_environment() {
270
313
local project_hash="\${project_basename}_$(echo "$md5hash" | cut -c1-8)"
271
314
272
315
# Check for dependency file to add dependency hash
316
+ # IMPORTANT: keep this list in sync with DEPENDENCY_FILE_NAMES in src/env.ts
273
317
local dep_file=""
274
- for name in "dependencies.yaml" "deps.yaml" "pkgx.yaml" "package.json "; do
318
+ for name in "\${_dep_names[@]} "; do
275
319
if [[ -f "$project_dir/$name" ]]; then
276
320
dep_file="$project_dir/$name"
277
321
break
278
322
fi
279
323
done
280
324
281
325
local env_dir="$HOME/.local/share/launchpad/envs/$project_hash"
326
+ local dep_short=""
282
327
if [[ -n "$dep_file" ]]; then
283
- local dep_short=$(LAUNCHPAD_DISABLE_SHELL_INTEGRATION=1 ${ launchpadBinary } dev:md5 "$dep_file" 2>/dev/null | cut -c1-8 || echo "")
328
+ dep_short=$(LAUNCHPAD_DISABLE_SHELL_INTEGRATION=1 ${ launchpadBinary } dev:md5 "$dep_file" 2>/dev/null | cut -c1-8 || echo "")
284
329
if [[ -n "$dep_short" ]]; then
285
330
env_dir="\${env_dir}-d\${dep_short}"
286
331
fi
287
332
fi
288
333
334
+ if [[ "$verbose_mode" == "true" && "$__lp_should_verbose_print" == "1" ]]; then
335
+ printf "🔎 dep_file=%q dep_short=%s env_dir=%q\n" "$dep_file" "$dep_short" "$env_dir" >&2
336
+ fi
337
+
289
338
# Check if we're switching projects
290
339
if [[ -n "$LAUNCHPAD_CURRENT_PROJECT" && "$LAUNCHPAD_CURRENT_PROJECT" != "$project_dir" ]]; then
291
340
# Remove old project paths from PATH
@@ -334,8 +383,21 @@ __launchpad_switch_environment() {
334
383
fi
335
384
336
385
if [[ "$should_attempt" -eq 1 ]]; then
337
- # Suppress installer output in hooks to avoid stray blank lines in the prompt
338
- if LAUNCHPAD_DISABLE_SHELL_INTEGRATION=1 LAUNCHPAD_SHELL_INTEGRATION=1 ${ launchpadBinary } install "$project_dir" >/dev/null 2>&1; then
386
+ # Run installer; show output if verbose, otherwise suppress to keep prompt clean
387
+ if [[ "$verbose_mode" == "true" && "$__lp_should_verbose_print" == "1" ]]; then
388
+ printf "🚀 Starting on-demand install for %q\n" "$project_dir" >&2
389
+ fi
390
+
391
+ if [[ "$verbose_mode" == "true" ]]; then
392
+ # In verbose mode, avoid LAUNCHPAD_SHELL_INTEGRATION=1 so installer prints logs
393
+ LAUNCHPAD_DISABLE_SHELL_INTEGRATION=1 ${ launchpadBinary } install "$project_dir"
394
+ install_status=$?
395
+ else
396
+ LAUNCHPAD_DISABLE_SHELL_INTEGRATION=1 LAUNCHPAD_SHELL_INTEGRATION=1 ${ launchpadBinary } install "$project_dir" >/dev/null 2>&1
397
+ install_status=$?
398
+ fi
399
+
400
+ if [[ $install_status -eq 0 ]]; then
339
401
if [[ "$verbose_mode" == "true" && "$__lp_should_verbose_print" == "1" ]]; then
340
402
printf "📦 Installed project dependencies (on-demand)\n" >&2
341
403
fi
@@ -356,7 +418,7 @@ __launchpad_switch_environment() {
356
418
# Touch backoff marker only on failure to avoid repeated attempts
357
419
: > "$backoff_marker" 2>/dev/null || true
358
420
if [[ "$verbose_mode" == "true" && "$__lp_should_verbose_print" == "1" ]]; then
359
- printf "⏭️ Deferred on -demand install. Run 'launchpad install %q' manually.\n" "$project_dir" >&2
421
+ printf "❌ On -demand install failed (exit %d) . Run 'launchpad install %q' manually.\n" "$install_status " "$project_dir" >&2
360
422
fi
361
423
fi
362
424
else
0 commit comments