Skip to content

fix(extract): resolve bash source edges built from ${VAR} paths (#2079)#2139

Closed
HerenderKumar wants to merge 1 commit into
Graphify-Labs:v8from
HerenderKumar:bash-var-source-2079
Closed

fix(extract): resolve bash source edges built from ${VAR} paths (#2079)#2139
HerenderKumar wants to merge 1 commit into
Graphify-Labs:v8from
HerenderKumar:bash-var-source-2079

Conversation

@HerenderKumar

Copy link
Copy Markdown
Contributor

Fixes #2079

When a bash script sources a file through a variable path like:

source "${BENCH_DIR}/lib/gpu-discover.sh"

graphify was putting the literal ${BENCH_DIR} text into the edge target, so the edge pointed at nothing, got flagged as dangling, and was dropped. The end result was that shared shell libraries looked orphaned and got split off into their own communities.

This adds a small branch for variable-built source paths:

  • strip the leading ${VAR} / $VAR part,
  • resolve the rest against the script's own folder (which is exactly what the common dirname "${BASH_SOURCE[0]}" idiom makes the variable point to),
  • only emit the edge (as INFERRED) when the file actually exists on disk — otherwise skip it instead of writing a dead id.

Plain source ./x.sh and bare-name sources behave exactly as before.

I checked it end-to-end: building the repro repo now links the sourcing script straight to the real library node, with zero dangling edges.

Tests: two new cases in tests/test_extract.py — the ${VAR} idiom resolves to the real file, and an unmatched ${VAR} path emits no edge. Full extract + symbol-resolution suites pass (182 passed, 1 skipped).

…hify-Labs#2079)

`source "${BENCH_DIR}/lib/x.sh"` (the `dirname "${BASH_SOURCE[0]}"` idiom)
took the bare-name branch, which baked the unexpanded `${BENCH_DIR}` text
into the target id via `_make_id`. That id matches no node, so the edge was
flagged dangling and dropped at export — shared shell libraries looked
orphaned and were split into separate communities.

Detect a `$`-expansion in the source argument, strip the leading
expansion segment(s), and resolve the literal suffix against the script's
own directory (which is what the canonical idiom makes the variable). Emit
`imports_from` as INFERRED only when it resolves to a real file on disk;
skip otherwise instead of emitting a dead id. Bare-name sources keep their
existing behavior.
@HerenderKumar

Copy link
Copy Markdown
Contributor Author

Quick note on scope: this PR fixes the source-edge half of the bash sourcing problem — source "${VAR}/lib.sh" now resolves to the real file instead of a dead id.

It deliberately leaves a second, related thing alone: a call to a function that's defined in a sourced file still doesn't get a calls edge — even with a plain source ./lib.sh where the source edge already resolves. That's a separate gap in the bash call extractor/resolver, so I've filed it on its own as #2141 to keep this PR small and focused.

safishamsi added a commit that referenced this pull request Jul 24, 2026
#2139)

The #2139 ${VAR} source handler now also records bash_sources so
resolve_bash_source_edges binds calls into the sourced lib's functions,
not just the source edge. Add the end-to-end oracle plus the previously
untested _bash_source_suffix guards (mid-path $, whole-var, .. traversal
fabricate nothing).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@safishamsi

Copy link
Copy Markdown
Collaborator

Thanks @HerenderKumar. Shipped in v0.9.26 (cherry-picked to v8 as 0019fc4 to preserve your authorship). During the merge with #2157 I added one integration line so calls into a ${VAR}-sourced library also resolve, not just the source edge. Closed-unmerged here, but it is in the release: https://github.com/Graphify-Labs/graphify/releases/tag/v0.9.26

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.

Bash: source "${VAR}/lib.sh" emits an unresolvable edge — sourced libraries appear orphaned

2 participants