Skip to content

Commit 21c1266

Browse files
committed
Fix CppLibrary::vendor_bundle? to use "bundle show" paths intead of assuming vendor/bundle
1 parent c9c8bf1 commit 21c1266

File tree

2 files changed

+45
-10
lines changed

2 files changed

+45
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2121
### Fixed
2222
- Library installation no longer "fails" if the library is already installed
2323
- Platform definition for `mega2560` now includes proper AVR compiler flag
24+
- `CppLibrary::vendor_bundle?` now asks where gems are, instead of assuming `vendor/bundle/`
2425

2526
### Security
2627

lib/arduino_ci/cpp_library.rb

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ class CppLibrary
3232
# @return [String] the last command
3333
attr_reader :last_cmd
3434

35+
# @return [Array<Pathname>] Directories suspected of being vendor-bundle
36+
attr_reader :vendor_bundle_cache
37+
3538
# @param base_dir [Pathname] The path to the library being tested
3639
# @param arduino_lib_dir [Pathname] The path to the libraries directory
3740
def initialize(base_dir, arduino_lib_dir)
@@ -45,26 +48,57 @@ def initialize(base_dir, arduino_lib_dir)
4548
@last_out = ""
4649
@last_msg = ""
4750
@has_libasan_cache = {}
51+
@vendor_bundle_cache = nil
4852
end
4953

5054
# Guess whether a file is part of the vendor bundle (indicating we should ignore it).
5155
#
52-
# This assumes the vendor bundle will be at `vendor/bundle` and not some other location
56+
# A safe way to do this seems to be to check whether any of the installed gems
57+
# appear to be a subdirectory of (but not equal to) the working directory.
58+
# That gets us the vendor directory (or multiple directories). We can check
59+
# if the given path is contained by any of those.
60+
#
5361
# @param path [Pathname] The path to check
5462
# @return [bool]
5563
def vendor_bundle?(path)
56-
# TODO: look for Gemfile, look for .bundle/config and get BUNDLE_PATH from there?
57-
base = @base_dir + "vendor"
58-
return false unless base.exist?
64+
# use a cache to be kind to the filesystem
65+
if @vendor_bundle_cache == false
66+
# no bundle
67+
return false
68+
elsif @vendor_bundle_cache.nil?
69+
# if the bundle show command fails, assume there isn't a bundle
70+
bundle_info = Host.run_and_capture("bundle show --paths")
71+
unless bundle_info[:success]
72+
@vendor_bundle_cache = false
73+
return false
74+
end
5975

60-
vendor_bundle_aliases = [base, base.realpath]
76+
# by preemptively switching to the parent directory, we can both ensure that
77+
# we miss any gems that are equal to the working directory AND exploit some
78+
# commonality in the paths to cut down our search locations
79+
#
80+
# NOT REJECTING THE WORKING DIRECTORY IS SUPER IMPORTANT because if we do,
81+
# we won't be able to run CI on this library itself.
82+
bundle_paths = bundle_info[:out].lines
83+
.map { |l| Pathname.new(l.chomp) }
84+
.select(&:exist?)
85+
.map(&:realpath)
86+
.map(&:parent)
87+
.uniq
88+
wd = Pathname.new(".").realpath
89+
@vendor_bundle_cache = bundle_paths.select do |gem_path|
90+
gem_path.ascend do |part|
91+
break true if wd == part
92+
end
93+
end
94+
end
6195

62-
# we could do this but some rubies don't return an enumerator for ascend
63-
# path.ascend.any? { |part| vendor_bundle_aliases.include?(part) }
64-
path.ascend do |part|
65-
return true if vendor_bundle_aliases.include?(part)
96+
# With vendor bundles located, check this file against those
97+
@vendor_bundle_cache.any? do |gem_path|
98+
path.ascend do |part|
99+
break true if gem_path == part
100+
end
66101
end
67-
false
68102
end
69103

70104
# Guess whether a file is part of the tests/ dir (indicating library compilation should ignore it).

0 commit comments

Comments
 (0)