-
Notifications
You must be signed in to change notification settings - Fork 125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: [Tapioca Addon] Support gem RBI generation on dirty lockfile #2081
base: tapioca-addon-feature-branch
Are you sure you want to change the base?
WIP: [Tapioca Addon] Support gem RBI generation on dirty lockfile #2081
Conversation
lib/ruby_lsp/tapioca/addon.rb
Outdated
current_lockfile = File.read("Gemfile.lock") | ||
snapshot_lockfile = File.read(GEMFILE_LOCK_SNAPSHOT) if File.exist?(GEMFILE_LOCK_SNAPSHOT) | ||
|
||
unless snapshot_lockfile |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have we compared the snapshot approach to git diff
? I can think of one scenario where you update the lockfile before snapshot is created so upon the consequent restart there are changes in git status
however, snapshot doesn't exist yet so we don't generate. It's not a common scenario so not important. But feels like running git diff
instead is a viable solution. Curious about the reasoning here. Does it have downsides for changing branches?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for mentioning git diff
again. I looked into it with more attention and I do agree it is a much nicer solution.
I have pushed a refactor to take advantage of git diff
. Let me know what you think.
lib/ruby_lsp/tapioca/addon.rb
Outdated
def handle_gemfile_changes | ||
return unless File.exist?(".git") | ||
|
||
gemfile_status = %x(git status --porcelain Gemfile.lock).strip |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With shelling out and the file parsing I'm curious how long this adds to the boot time. Could you add some simple timings to the PR description, before and after this change for core?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is now an older implementation, but I do agree some timings would be nice to have. I'll take a look on Monday.
cc19ba0
to
3ce0a60
Compare
To support gem RBI generation, we needed a way to detect changes in Gemfile.lock. Currently, changes to this file cause the Ruby LSP to restart, resulting in loss of access to any previous state information. By creating a snapshot of Gemfile.lock, we can persist data across server restarts. Upon restart, we parse both the snapshot and current Gemfile.lock using Bundler::LockfileParser. If differences are found, we extract the relevant gem names and specifications, allowing us to trigger the gem RBI generation.
Only regenerate RBIs when Gemfile.lock has uncommitted changes in git, which targets manual bundle updates. This improves performance by avoiding unnecessary regeneration during normal git operations.
351a2fb
to
f387c8d
Compare
WIP
This Draft PR is still a work in progress and an alternative implementation to #2063
Motivation
To support gem RBI generation, we needed a way to detect changes in
Gemfile.lock
. Currently, changes to this file cause the Ruby LSP to restart, resulting in loss of access to any previous state information. This limitation prevents monitoring and processing of gem changes.Implementation
We've implemented a solution that uses
git diff
to trackGemfile.lock
changes:Change Detection
git_repo?
check to ensure we're in a git repositorygit diff HEAD Gemfile.lock
to detect uncommitted changesGem Change Analysis
LockfileDiffParser
class to analyze diff outputGem RBI Processing
Key Components
Addon
: MonitorsGemfile.lock
changes and notifies theServerAddon
when changes are detectedLockfileDiffParser
: Analyzes git diff output to identify added, modified, and removed gemsServerAddon
: Triggers the execution of the actual RBI file operations (removal or generation)This approach specifically targets manual bundle updates while avoiding unnecessary RBI regeneration during normal git operations like branch switches.
Previous Implementation
To address this, we check git status to determine ifGemfile.lock
has uncommitted changes. When changes are detected, we:1. Compare the currentGemfile.lock
with a snapshot stored intmp/tapioca/.gemfile_lock_snapshot
2. UseBundler::LockfileParser
to parse both files and detect:- Removed gems (present in snapshot but not in current)- Changed gems (version differences between snapshot and current)3. Process the changes in the server addon:- Remove RBI files for deleted gems- Generate new RBI files for changed gems using Tapioca4. Update the snapshot with the current lockfile contentTests