@@ -32,6 +32,9 @@ class CppLibrary
32
32
# @return [String] the last command
33
33
attr_reader :last_cmd
34
34
35
+ # @return [Array<Pathname>] Directories suspected of being vendor-bundle
36
+ attr_reader :vendor_bundle_cache
37
+
35
38
# @param base_dir [Pathname] The path to the library being tested
36
39
# @param arduino_lib_dir [Pathname] The path to the libraries directory
37
40
def initialize ( base_dir , arduino_lib_dir )
@@ -45,26 +48,57 @@ def initialize(base_dir, arduino_lib_dir)
45
48
@last_out = ""
46
49
@last_msg = ""
47
50
@has_libasan_cache = { }
51
+ @vendor_bundle_cache = nil
48
52
end
49
53
50
54
# Guess whether a file is part of the vendor bundle (indicating we should ignore it).
51
55
#
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
+ #
53
61
# @param path [Pathname] The path to check
54
62
# @return [bool]
55
63
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
+ # Cache bundle information, as it is (1) time consuming to fetch and (2) not going to change while we run
65
+ if @vendor_bundle_cache . nil?
66
+ bundle_info = Host . run_and_capture ( "bundle show --paths" )
67
+ if !bundle_info [ :success ]
68
+ # if the bundle show command fails, assume there isn't a bundle
69
+ @vendor_bundle_cache = false
70
+ else
71
+ # Get all the places where gems are stored. We combine a few things here:
72
+ # by preemptively switching to the parent directory, we can both ensure that
73
+ # we skip any gems that are equal to the working directory AND exploit some
74
+ # commonality in the paths to cut down our search locations
75
+ #
76
+ # NOT CONFUSING THE WORKING DIRECTORY WITH VENDOR BUNDLE IS SUPER IMPORTANT
77
+ # because if we do, we won't be able to run CI on this library itself.
78
+ bundle_paths = bundle_info [ :out ] . lines
79
+ . map { |l | Pathname . new ( l . chomp ) }
80
+ . select ( &:exist? )
81
+ . map ( &:realpath )
82
+ . map ( &:parent )
83
+ . uniq
84
+ wd = Pathname . new ( "." ) . realpath
85
+ @vendor_bundle_cache = bundle_paths . select do |gem_path |
86
+ gem_path . ascend do |part |
87
+ break true if wd == part
88
+ end
89
+ end
90
+ end
91
+ end
59
92
60
- vendor_bundle_aliases = [ base , base . realpath ]
93
+ # no bundle existed
94
+ return false if @vendor_bundle_cache == false
61
95
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
66
101
end
67
- false
68
102
end
69
103
70
104
# Guess whether a file is part of the tests/ dir (indicating library compilation should ignore it).
0 commit comments