Bugfix: path dependencies module resolution bug with local paths#4563
Conversation
lpil
left a comment
There was a problem hiding this comment.
Sorry this took so long for me to review! I missed it somehow, and I've only just seen it now.
Thank you for this, I've left some comments inline. Tests will need to be added too.
| // which indicates that their dependencies have changed | ||
| for (key, requirement2) in requirements2 { | ||
| if let Requirement::Path { path } = requirement2 { | ||
| let dep_manifest_path = root_path.join(path).join("manifest.toml"); |
There was a problem hiding this comment.
All path manipulation must be done in the ProjectPaths class, no other code is permitted to use .join etc.
|
|
||
| // We used to always force clean artifacts for path dependencies, | ||
| // but now we use the gleam.toml hash tracking in is_same_requirements | ||
| // to determine when path dependency dependencies have changed |
There was a problem hiding this comment.
caught my GPT generated snippet. Sorry, removing it.
|
|
||
| // For path dependencies, we need to check if their manifest.toml files have changed, | ||
| // which indicates that their dependencies have changed | ||
| for (key, requirement2) in requirements2 { |
There was a problem hiding this comment.
This equality checking logic should be in the same_requirements function as that's the one that checks equality, while this one iterates over the collection.
There was a problem hiding this comment.
yeah, I removed the comment
| } | ||
| }; | ||
|
|
||
| let mut hasher = std::hash::DefaultHasher::new(); |
There was a problem hiding this comment.
We use xxhash_rust::xxh3::xxh3_64 for fingerprinting, not the default hasher.
| tracing::debug!("cannot_read_path_dependency_manifest_forcing_rebuild"); | ||
| return Ok(false); | ||
| } | ||
| }; |
There was a problem hiding this comment.
We check mtimes before we hash, to avoid extra work, so let's add that here.
| // If cached hash file doesn't exist, this is the first time we're checking this dependency | ||
| if !cached_hash_path.exists() { | ||
| // Save the current hash for future comparisons | ||
| if let Err(e) = fs::write(&cached_hash_path, ¤t_hash) { |
There was a problem hiding this comment.
The errors in this code are being silently discarded! They must always be passed back up.
|
|
||
| if !dep_manifest_path.exists() { | ||
| tracing::debug!("path_dependency_manifest_not_found_forcing_rebuild"); | ||
| return Ok(false); |
There was a problem hiding this comment.
This would result in rebuilding every single time when there's no manifest for the path dep!
There was a problem hiding this comment.
Sorry! continue-ing instead now
| } | ||
| } | ||
|
|
||
| // For path dependencies, we need to check if their manifest.toml files have changed, |
There was a problem hiding this comment.
The name for this function doesn't fit what it does any more- even if the requirements are the same the function can return false in the instance that the definition of one of the required deps has changed.
The functions have also been made effectful and to depend on file system state, so that would need to be communicated clearly in the name and arguments too.
These functions that check the requirements are the same could go unchanged (which would still fit the "is same requirements" name) and a new function could be created to check just the path deps have not changed their deps.
There was a problem hiding this comment.
pushed an update!
|
@lpil Addressed all comments! Also added tests, that you can checkout. Thank you for the input! |
|
Hello! If this is ready please remember to un-draft it, also would you mind rebasing on main? It seems there's some conflicts |
i'll get on rebasing! |
358a62f to
a2c41e2
Compare
|
@lpil @giacomocavalieri ready to merge from my end! |
After rebasing onto upstream/main, the dependency resolution logic was refactored into DependencyManager. This commit adapts the fix to work with the new architecture by: - Making is_same_requirements and are_path_dependency_manifests_unchanged pub(crate) so they can be used from dependency_manager.rs - Adding the path dependency manifest check to DependencyManager::resolve_versions - Updating tests to use the renamed function
The hashbrown version change (0.15.3 -> 0.15.5) altered HashMap iteration order, causing dependency resolution tests to fail. Restored upstream's Cargo.lock and rebuilt to include our dependencies.
945a8cd to
efecdb7
Compare
Code to fix #2278
I hope this is an acceptable solution, I've inspected closed PRs that didn't make it attempting to fix this issue (#2334 and #3398).
In summary this approach stores a hash of the manifest.toml of all dependencies that are a path dependencies in the build directory and rebuilds any packages if the manifest.toml should change.
Let me know if I've missed anything or if this approach does not scale well, thank you!
Also I did not want to clutter the codebase with it, but here is a script (thank you GPT) to test the scenario that produces the error mentioned in the linked issue. It assumes you're running it in the root of the gleam codebase, otherwise you can adjust the
GLEAM_BINpath. Also this script probably only works on a mac or linux. Here is the script: