Skip to content

Fix vendor_bundle? behavior in CppLibrary (no longer hard-code bundle location) #98

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

Merged
merged 1 commit into from
Jan 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Fixed
- Library installation no longer "fails" if the library is already installed
- Platform definition for `mega2560` now includes proper AVR compiler flag
- `CppLibrary::vendor_bundle?` now asks where gems are, instead of assuming `vendor/bundle/`

### Security

Expand Down
54 changes: 44 additions & 10 deletions lib/arduino_ci/cpp_library.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class CppLibrary
# @return [String] the last command
attr_reader :last_cmd

# @return [Array<Pathname>] Directories suspected of being vendor-bundle
attr_reader :vendor_bundle_cache

# @param base_dir [Pathname] The path to the library being tested
# @param arduino_lib_dir [Pathname] The path to the libraries directory
def initialize(base_dir, arduino_lib_dir)
Expand All @@ -45,26 +48,57 @@ def initialize(base_dir, arduino_lib_dir)
@last_out = ""
@last_msg = ""
@has_libasan_cache = {}
@vendor_bundle_cache = nil
end

# Guess whether a file is part of the vendor bundle (indicating we should ignore it).
#
# This assumes the vendor bundle will be at `vendor/bundle` and not some other location
# A safe way to do this seems to be to check whether any of the installed gems
# appear to be a subdirectory of (but not equal to) the working directory.
# That gets us the vendor directory (or multiple directories). We can check
# if the given path is contained by any of those.
#
# @param path [Pathname] The path to check
# @return [bool]
def vendor_bundle?(path)
# TODO: look for Gemfile, look for .bundle/config and get BUNDLE_PATH from there?
base = @base_dir + "vendor"
return false unless base.exist?
# Cache bundle information, as it is (1) time consuming to fetch and (2) not going to change while we run
if @vendor_bundle_cache.nil?
bundle_info = Host.run_and_capture("bundle show --paths")
if !bundle_info[:success]
# if the bundle show command fails, assume there isn't a bundle
@vendor_bundle_cache = false
else
# Get all the places where gems are stored. We combine a few things here:
# by preemptively switching to the parent directory, we can both ensure that
# we skip any gems that are equal to the working directory AND exploit some
# commonality in the paths to cut down our search locations
#
# NOT CONFUSING THE WORKING DIRECTORY WITH VENDOR BUNDLE IS SUPER IMPORTANT
# because if we do, we won't be able to run CI on this library itself.
bundle_paths = bundle_info[:out].lines
.map { |l| Pathname.new(l.chomp) }
.select(&:exist?)
.map(&:realpath)
.map(&:parent)
.uniq
wd = Pathname.new(".").realpath
@vendor_bundle_cache = bundle_paths.select do |gem_path|
gem_path.ascend do |part|
break true if wd == part
end
end
end
end

vendor_bundle_aliases = [base, base.realpath]
# no bundle existed
return false if @vendor_bundle_cache == false

# we could do this but some rubies don't return an enumerator for ascend
# path.ascend.any? { |part| vendor_bundle_aliases.include?(part) }
path.ascend do |part|
return true if vendor_bundle_aliases.include?(part)
# With vendor bundles located, check this file against those
@vendor_bundle_cache.any? do |gem_path|
path.ascend do |part|
break true if gem_path == part
end
end
false
end

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