Skip to content

Commit

Permalink
Fix pacman install within a parallel bundler install -jX
Browse files Browse the repository at this point in the history
pacman invocation must be serialized to avoid locking error.

Fixes #397
  • Loading branch information
larskanis committed Nov 21, 2024
1 parent 0064fe7 commit 05ee81c
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 16 deletions.
35 changes: 21 additions & 14 deletions lib/ruby_installer/build/msys2_installation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -319,29 +319,36 @@ def disable_msys_apps_per_ps1
end.join(";")
end

@@pacman_lock = Mutex.new
private def with_pacman_lock(&block)
@@pacman_lock.synchronize(&block)
end

def install_packages(packages, verbose: false)
return if packages.empty?

with_msys_apps_enabled do
# Find packages that are already installed
skips, installs = packages.partition do |package|
IO.popen(["pacman", "-Q", package], err: :out, &:read)
$?.success?
end
with_pacman_lock do
# Find packages that are already installed
skips, installs = packages.partition do |package|
IO.popen(["pacman", "-Q", package], err: :out, &:read)
$?.success?
end

Gem.ui.say("Using msys2 packages: #{skips.join(" ")}") if verbose && skips.any?
Gem.ui.say("Using msys2 packages: #{skips.join(" ")}") if verbose && skips.any?

# Install required packages
if installs.any?
Gem.ui.say("Installing required msys2 packages: #{installs.join(" ")}") if verbose
# Install required packages
if installs.any?
Gem.ui.say("Installing required msys2 packages: #{installs.join(" ")}") if verbose

args = ["pacman", "-S", "--needed", "--noconfirm", *installs]
Gem.ui.say("> #{args.join(" ")}") if verbose==1
args = ["pacman", "-S", "--needed", "--noconfirm", *installs]
Gem.ui.say("> #{args.join(" ")}") if verbose==1

res = IO.popen(args, &:read)
raise CommandError, "pacman failed with the following output:\n#{res}" if !$? || $?.exitstatus != 0
res = IO.popen(args, &:read)
raise CommandError, "pacman failed with the following output:\n#{res}" if !$? || $?.exitstatus != 0

Gem.ui.say(res) if verbose==1
Gem.ui.say(res) if verbose==1
end
end
end
end
Expand Down
1 change: 1 addition & 0 deletions test/helper/testgem/Gemfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
source "https://dummy-url.nonexit"
gem "testgem2", "1.0.0"
gem "testgem", "1.0.0"
6 changes: 4 additions & 2 deletions test/test_gem_install.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,17 @@ def test_bundle_install
res = system <<-EOT.gsub("\n", "&")
cd test/helper/testgem
gem build testgem.gemspec
gem build testgem2.gemspec
copy /b testgem-1.0.0.gem "vendor/cache/"
bundle install --local
copy /b testgem2-1.0.0.gem "vendor/cache/"
bundle install --local -j16
EOT
assert res, "shell commands should succeed"

out = IO.popen("bundle exec ruby -rtestgem -e \"puts Libguess.determine_encoding('abc', 'Greek')\"", chdir: "test/helper/testgem", &:read)
assert_match(/UTF-8/, out.scrub, "call the ruby API of the testgem")

assert system("gem uninstall testgem --executables --force"), "uninstall testgem"
assert system("gem uninstall testgem testgem2 --executables --force"), "uninstall testgem"
FileUtils.rm("test/helper/testgem/testgem-1.0.0.gem")
end

Expand Down

0 comments on commit 05ee81c

Please sign in to comment.