Merge branch 'master' of github.com:Homebrew/brew into update-compiler-docs
This commit is contained in:
commit
fd84bcbff7
10
.travis.yml
10
.travis.yml
@ -1,20 +1,22 @@
|
||||
language: c
|
||||
language: ruby
|
||||
rvm: system
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/Library/Caches/Homebrew/style
|
||||
- $HOME/Library/Caches/Homebrew/tests
|
||||
- Library/Homebrew/vendor/bundle
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- os: osx
|
||||
compiler: clang
|
||||
osx_image: xcode9.2
|
||||
osx_image: xcode9.4
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
sudo: false
|
||||
|
||||
before_install:
|
||||
|
@ -104,10 +104,8 @@ then
|
||||
HOMEBREW_FORCE_BREWED_GIT="1"
|
||||
fi
|
||||
|
||||
if [[ -z "$HOMEBREW_CACHE" ]]
|
||||
then
|
||||
HOMEBREW_CACHE="$HOME/Library/Caches/Homebrew"
|
||||
fi
|
||||
HOMEBREW_CACHE="${HOMEBREW_CACHE:-${HOME}/Library/Caches/Homebrew}"
|
||||
HOMEBREW_SYSTEM_TEMP="/private/tmp"
|
||||
else
|
||||
HOMEBREW_PROCESSOR="$(uname -m)"
|
||||
HOMEBREW_PRODUCT="${HOMEBREW_SYSTEM}brew"
|
||||
@ -115,17 +113,13 @@ else
|
||||
: "${HOMEBREW_OS_VERSION:=$(uname -r)}"
|
||||
HOMEBREW_OS_USER_AGENT_VERSION="$HOMEBREW_OS_VERSION"
|
||||
|
||||
if [[ -z "$HOMEBREW_CACHE" ]]
|
||||
then
|
||||
if [[ -n "$XDG_CACHE_HOME" ]]
|
||||
then
|
||||
HOMEBREW_CACHE="$XDG_CACHE_HOME/Homebrew"
|
||||
else
|
||||
HOMEBREW_CACHE="$HOME/.cache/Homebrew"
|
||||
fi
|
||||
fi
|
||||
CACHE_HOME="${XDG_CACHE_HOME:-${HOME}/.cache}"
|
||||
HOMEBREW_CACHE="${HOMEBREW_CACHE:-${CACHE_HOME}/Homebrew}"
|
||||
HOMEBREW_SYSTEM_TEMP="/tmp"
|
||||
fi
|
||||
|
||||
HOMEBREW_TEMP="${HOMEBREW_TEMP:-${HOMEBREW_SYSTEM_TEMP}}"
|
||||
|
||||
if [[ -n "$HOMEBREW_FORCE_BREWED_CURL" &&
|
||||
-x "$HOMEBREW_PREFIX/opt/curl/bin/curl" ]] &&
|
||||
"$HOMEBREW_PREFIX/opt/curl/bin/curl" --version >/dev/null
|
||||
@ -153,6 +147,8 @@ export HOMEBREW_BREW_FILE
|
||||
export HOMEBREW_PREFIX
|
||||
export HOMEBREW_REPOSITORY
|
||||
export HOMEBREW_LIBRARY
|
||||
export HOMEBREW_SYSTEM_TEMP
|
||||
export HOMEBREW_TEMP
|
||||
|
||||
# Declared in brew.sh
|
||||
export HOMEBREW_VERSION
|
||||
@ -309,6 +305,21 @@ EOS
|
||||
}
|
||||
check-run-command-as-root
|
||||
|
||||
check-prefix-is-not-tmpdir() {
|
||||
[[ -z "${HOMEBREW_MACOS}" ]] && return
|
||||
|
||||
if [[ "${HOMEBREW_PREFIX}" = "${HOMEBREW_TEMP}"* ]]
|
||||
then
|
||||
odie <<EOS
|
||||
Your HOMEBREW_PREFIX is in the Homebrew temporary directory, which Homebrew
|
||||
uses to store downloads and builds. You can resolve this by installing Homebrew to
|
||||
either the standard prefix (/usr/local) or to a non-standard prefix that is not
|
||||
in the Homebrew temporary directory.
|
||||
EOS
|
||||
fi
|
||||
}
|
||||
check-prefix-is-not-tmpdir
|
||||
|
||||
if [[ "$HOMEBREW_PREFIX" = "/usr/local" &&
|
||||
"$HOMEBREW_PREFIX" != "$HOMEBREW_REPOSITORY" &&
|
||||
"$HOMEBREW_CELLAR" = "$HOMEBREW_REPOSITORY/Cellar" ]]
|
||||
|
@ -201,21 +201,20 @@ module Hbc
|
||||
|
||||
def check_hosting_with_appcast
|
||||
return if cask.appcast
|
||||
check_github_releases_appcast
|
||||
check_sourceforge_appcast
|
||||
end
|
||||
|
||||
def check_github_releases_appcast
|
||||
return unless cask.url.to_s =~ %r{github.com/([^/]+)/([^/]+)/releases/download/(\S+)}
|
||||
add_appcast = "please add an appcast. See https://github.com/Homebrew/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/appcast.md"
|
||||
|
||||
add_warning "Download uses GitHub releases, please add an appcast. See https://github.com/Homebrew/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/appcast.md"
|
||||
end
|
||||
|
||||
def check_sourceforge_appcast
|
||||
return if cask.version.latest?
|
||||
return unless cask.url.to_s =~ %r{sourceforge.net/(\S+)}
|
||||
|
||||
add_warning "Download is hosted on SourceForge, please add an appcast. See https://github.com/Homebrew/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/appcast.md"
|
||||
case cask.url.to_s
|
||||
when %r{github.com/([^/]+)/([^/]+)/releases/download/(\S+)}
|
||||
add_warning "Download uses GitHub releases, #{add_appcast}"
|
||||
when %r{sourceforge.net/(\S+)}
|
||||
return if cask.version.latest?
|
||||
add_warning "Download is hosted on SourceForge, #{add_appcast}"
|
||||
when %r{dl.devmate.com/(\S+)}
|
||||
add_warning "Download is hosted on DevMate, #{add_appcast}"
|
||||
when %r{rink.hockeyapp.net/(\S+)}
|
||||
add_warning "Download is hosted on HockeyApp, #{add_appcast}"
|
||||
end
|
||||
end
|
||||
|
||||
def check_url
|
||||
|
@ -62,13 +62,11 @@ module Homebrew
|
||||
if tap.installed?
|
||||
info += tap.pinned? ? "pinned" : "unpinned"
|
||||
info += ", private" if tap.private?
|
||||
if (formula_count = tap.formula_files.size).positive?
|
||||
info += ", #{Formatter.pluralize(formula_count, "formula")}"
|
||||
info += if (contents = tap.contents).empty?
|
||||
", no commands/casks/formulae"
|
||||
else
|
||||
", #{contents.join(", ")}"
|
||||
end
|
||||
if (command_count = tap.command_files.size).positive?
|
||||
info += ", #{Formatter.pluralize(command_count, "command")}"
|
||||
end
|
||||
info += ", no formulae/commands" if (formula_count + command_count).zero?
|
||||
info += "\n#{tap.path} (#{tap.path.abv})"
|
||||
info += "\nFrom: #{tap.remote.nil? ? "N/A" : tap.remote}"
|
||||
else
|
||||
|
@ -39,7 +39,13 @@ HOMEBREW_CACHE_FORMULA = HOMEBREW_CACHE/"Formula"
|
||||
HOMEBREW_LOGS = Pathname.new(ENV["HOMEBREW_LOGS"] || "~/Library/Logs/Homebrew/").expand_path
|
||||
|
||||
# Must use /tmp instead of $TMPDIR because long paths break Unix domain sockets
|
||||
HOMEBREW_TEMP = Pathname.new(ENV.fetch("HOMEBREW_TEMP", "/tmp"))
|
||||
HOMEBREW_TEMP = begin
|
||||
# /tmp fallback is here for people auto-updating from a version where
|
||||
# HOMEBREW_TEMP isn't set.
|
||||
tmp = Pathname.new(ENV["HOMEBREW_TEMP"] || "/tmp")
|
||||
tmp.mkpath unless tmp.exist?
|
||||
tmp.realpath
|
||||
end
|
||||
|
||||
unless defined? HOMEBREW_LIBRARY_PATH
|
||||
# Root of the Homebrew code base
|
||||
|
@ -216,7 +216,7 @@ module Homebrew
|
||||
|
||||
def initialize(formula, options = {})
|
||||
@formula = formula
|
||||
@new_formula = options[:new_formula]
|
||||
@new_formula = options[:new_formula] && !formula.versioned_formula?
|
||||
@strict = options[:strict]
|
||||
@online = options[:online]
|
||||
@display_cop_names = options[:display_cop_names]
|
||||
@ -236,6 +236,7 @@ module Homebrew
|
||||
return unless @style_offenses
|
||||
@style_offenses.each do |offense|
|
||||
if offense.cop_name.start_with?("NewFormulaAudit")
|
||||
next if formula.versioned_formula?
|
||||
new_formula_problem offense.to_s(display_cop_name: @display_cop_names)
|
||||
next
|
||||
end
|
||||
@ -416,7 +417,6 @@ module Homebrew
|
||||
end
|
||||
|
||||
next unless @new_formula
|
||||
next if formula.versioned_formula?
|
||||
next unless @official_tap
|
||||
if dep.tags.include?(:recommended) || dep.tags.include?(:optional)
|
||||
new_formula_problem "Formulae should not have #{dep.tags} dependencies."
|
||||
@ -571,8 +571,19 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
if @new_formula && formula.head
|
||||
new_formula_problem "Formulae should not have a HEAD spec"
|
||||
if formula.head || formula.devel
|
||||
unstable_spec_message = "Formulae should not have an unstable spec"
|
||||
if @new_formula
|
||||
new_formula_problem unstable_spec_message
|
||||
elsif formula.versioned_formula?
|
||||
versioned_unstable_spec = %w[
|
||||
bash-completion@2
|
||||
imagemagick@6
|
||||
openssl@1.1
|
||||
python@2
|
||||
]
|
||||
problem unstable_spec_message unless versioned_unstable_spec.include?(formula.name)
|
||||
end
|
||||
end
|
||||
|
||||
throttled = %w[
|
||||
@ -586,7 +597,7 @@ module Homebrew
|
||||
throttled.each_slice(2).to_a.map do |a, b|
|
||||
next if formula.stable.nil?
|
||||
version = formula.stable.version.to_s.split(".").last.to_i
|
||||
if @strict && a.include?(formula.name) && version.modulo(b.to_i).nonzero?
|
||||
if @strict && a == formula.name && version.modulo(b.to_i).nonzero?
|
||||
problem "should only be updated every #{b} releases on multiples of #{b}"
|
||||
end
|
||||
end
|
||||
|
@ -31,49 +31,50 @@ module Homebrew
|
||||
|
||||
ENV["HOMEBREW_UPDATE_TEST"] = "1"
|
||||
|
||||
if args.to_tag?
|
||||
branch = if args.to_tag?
|
||||
ENV["HOMEBREW_UPDATE_TO_TAG"] = "1"
|
||||
branch = "stable"
|
||||
"stable"
|
||||
else
|
||||
branch = "master"
|
||||
"master"
|
||||
end
|
||||
|
||||
cd HOMEBREW_REPOSITORY
|
||||
start_commit = if commit = args.commit
|
||||
commit
|
||||
elsif date = args.before
|
||||
Utils.popen_read("git", "rev-list", "-n1", "--before=#{date}", "origin/master").chomp
|
||||
elsif args.to_tag?
|
||||
tags = Utils.popen_read("git", "tag", "--list", "--sort=-version:refname")
|
||||
previous_tag = tags.lines[1]
|
||||
previous_tag ||= begin
|
||||
if (HOMEBREW_REPOSITORY/".git/shallow").exist?
|
||||
safe_system "git", "fetch", "--tags", "--depth=1"
|
||||
tags = Utils.popen_read("git", "tag", "--list", "--sort=-version:refname")
|
||||
elsif OS.linux?
|
||||
tags = Utils.popen_read("git tag --list | sort -rV")
|
||||
start_commit, end_commit = nil
|
||||
cd HOMEBREW_REPOSITORY do
|
||||
start_commit = if commit = args.commit
|
||||
commit
|
||||
elsif date = args.before
|
||||
Utils.popen_read("git", "rev-list", "-n1", "--before=#{date}", "origin/master").chomp
|
||||
elsif args.to_tag?
|
||||
tags = Utils.popen_read("git", "tag", "--list", "--sort=-version:refname")
|
||||
previous_tag = tags.lines[1]
|
||||
previous_tag ||= begin
|
||||
if (HOMEBREW_REPOSITORY/".git/shallow").exist?
|
||||
safe_system "git", "fetch", "--tags", "--depth=1"
|
||||
tags = Utils.popen_read("git", "tag", "--list", "--sort=-version:refname")
|
||||
elsif OS.linux?
|
||||
tags = Utils.popen_read("git tag --list | sort -rV")
|
||||
end
|
||||
tags.lines[1]
|
||||
end
|
||||
tags.lines[1]
|
||||
previous_tag = previous_tag.to_s.chomp
|
||||
odie "Could not find previous tag in:\n#{tags}" if previous_tag.empty?
|
||||
previous_tag
|
||||
else
|
||||
Utils.popen_read("git", "rev-parse", "origin/master").chomp
|
||||
end
|
||||
previous_tag = previous_tag.to_s.chomp
|
||||
odie "Could not find previous tag in:\n#{tags}" if previous_tag.empty?
|
||||
previous_tag
|
||||
else
|
||||
Utils.popen_read("git", "rev-parse", "origin/master").chomp
|
||||
odie "Could not find start commit!" if start_commit.empty?
|
||||
|
||||
start_commit = Utils.popen_read("git", "rev-parse", start_commit).chomp
|
||||
odie "Could not find start commit!" if start_commit.empty?
|
||||
|
||||
end_commit = Utils.popen_read("git", "rev-parse", "HEAD").chomp
|
||||
odie "Could not find end commit!" if end_commit.empty?
|
||||
end
|
||||
odie "Could not find start commit!" if start_commit.empty?
|
||||
|
||||
start_commit = Utils.popen_read("git", "rev-parse", start_commit).chomp
|
||||
odie "Could not find start commit!" if start_commit.empty?
|
||||
|
||||
end_commit = Utils.popen_read("git", "rev-parse", "HEAD").chomp
|
||||
odie "Could not find end commit!" if end_commit.empty?
|
||||
|
||||
puts "Start commit: #{start_commit}"
|
||||
puts "End commit: #{end_commit}"
|
||||
|
||||
mktemp("update-test") do |staging|
|
||||
staging.retain! if args.keep_tmp?
|
||||
mkdir "update-test" do
|
||||
curdir = Pathname.new(Dir.pwd)
|
||||
|
||||
oh1 "Setup test environment..."
|
||||
@ -107,5 +108,7 @@ module Homebrew
|
||||
EOS
|
||||
end
|
||||
end
|
||||
ensure
|
||||
FileUtils.rm_r "update-test" unless args.keep_tmp?
|
||||
end
|
||||
end
|
||||
|
@ -90,53 +90,6 @@ class AbstractDownloadStrategy
|
||||
def quiet_safe_system(*args)
|
||||
safe_system(*expand_safe_system_args(args))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def xzpath
|
||||
"#{HOMEBREW_PREFIX}/opt/xz/bin/xz"
|
||||
end
|
||||
|
||||
def lzippath
|
||||
"#{HOMEBREW_PREFIX}/opt/lzip/bin/lzip"
|
||||
end
|
||||
|
||||
def lhapath
|
||||
"#{HOMEBREW_PREFIX}/opt/lha/bin/lha"
|
||||
end
|
||||
|
||||
def cvspath
|
||||
@cvspath ||= %W[
|
||||
/usr/bin/cvs
|
||||
#{HOMEBREW_PREFIX}/bin/cvs
|
||||
#{HOMEBREW_PREFIX}/opt/cvs/bin/cvs
|
||||
#{which("cvs")}
|
||||
].find { |p| File.executable? p }
|
||||
end
|
||||
|
||||
def hgpath
|
||||
@hgpath ||= %W[
|
||||
#{which("hg")}
|
||||
#{HOMEBREW_PREFIX}/bin/hg
|
||||
#{HOMEBREW_PREFIX}/opt/mercurial/bin/hg
|
||||
].find { |p| File.executable? p }
|
||||
end
|
||||
|
||||
def bzrpath
|
||||
@bzrpath ||= %W[
|
||||
#{which("bzr")}
|
||||
#{HOMEBREW_PREFIX}/bin/bzr
|
||||
#{HOMEBREW_PREFIX}/opt/bazaar/bin/bzr
|
||||
].find { |p| File.executable? p }
|
||||
end
|
||||
|
||||
def fossilpath
|
||||
@fossilpath ||= %W[
|
||||
#{which("fossil")}
|
||||
#{HOMEBREW_PREFIX}/bin/fossil
|
||||
#{HOMEBREW_PREFIX}/opt/fossil/bin/fossil
|
||||
].find { |p| File.executable? p }
|
||||
end
|
||||
end
|
||||
|
||||
class VCSDownloadStrategy < AbstractDownloadStrategy
|
||||
@ -224,43 +177,39 @@ end
|
||||
|
||||
class AbstractFileDownloadStrategy < AbstractDownloadStrategy
|
||||
def stage
|
||||
case type = cached_location.compression_type
|
||||
path = cached_location
|
||||
unpack_dir = Pathname.pwd
|
||||
|
||||
case type = path.compression_type
|
||||
when :zip
|
||||
quiet_safe_system "unzip", "-qq", cached_location
|
||||
safe_system "unzip", "-qq", path, "-d", unpack_dir
|
||||
chdir
|
||||
when :gzip_only
|
||||
buffered_write "gunzip"
|
||||
FileUtils.cp path, unpack_dir, preserve: true
|
||||
safe_system "gunzip", "-q", "-N", unpack_dir/path.basename
|
||||
when :bzip2_only
|
||||
buffered_write "bunzip2"
|
||||
FileUtils.cp path, unpack_dir, preserve: true
|
||||
safe_system "bunzip2", "-q", unpack_dir/path.basename
|
||||
when :gzip, :bzip2, :xz, :compress, :tar
|
||||
tar_flags = "x"
|
||||
if type == :gzip
|
||||
tar_flags << "z"
|
||||
elsif type == :bzip2
|
||||
tar_flags << "j"
|
||||
elsif type == :xz
|
||||
tar_flags << "J"
|
||||
end
|
||||
tar_flags << "f"
|
||||
if type == :xz && DependencyCollector.tar_needs_xz_dependency?
|
||||
pipe_to_tar xzpath
|
||||
pipe_to_tar "#{HOMEBREW_PREFIX}/opt/xz/bin/xz", unpack_dir
|
||||
else
|
||||
safe_system "tar", tar_flags, cached_location
|
||||
safe_system "tar", "xf", path, "-C", unpack_dir
|
||||
end
|
||||
chdir
|
||||
when :lzip
|
||||
pipe_to_tar lzippath
|
||||
pipe_to_tar "#{HOMEBREW_PREFIX}/opt/lzip/bin/lzip", unpack_dir
|
||||
chdir
|
||||
when :lha
|
||||
safe_system lhapath, "x", cached_location
|
||||
safe_system "#{HOMEBREW_PREFIX}/opt/lha/bin/lha", "xq2w=#{unpack_dir}", path
|
||||
when :xar
|
||||
safe_system "/usr/bin/xar", "-xf", cached_location
|
||||
safe_system "xar", "-x", "-f", path, "-C", unpack_dir
|
||||
when :rar
|
||||
quiet_safe_system "unrar", "x", "-inul", cached_location
|
||||
safe_system "unrar", "x", "-inul", path, unpack_dir
|
||||
when :p7zip
|
||||
safe_system "7zr", "x", cached_location
|
||||
safe_system "7zr", "x", "-y", "-bd", "-bso0", path, "-o#{unpack_dir}"
|
||||
else
|
||||
cp cached_location, basename_without_params, preserve: true
|
||||
cp path, unpack_dir/basename_without_params, preserve: true
|
||||
end
|
||||
end
|
||||
|
||||
@ -278,29 +227,17 @@ class AbstractFileDownloadStrategy < AbstractDownloadStrategy
|
||||
end
|
||||
end
|
||||
|
||||
def pipe_to_tar(tool)
|
||||
Utils.popen_read(tool, "-dc", cached_location.to_s) do |rd|
|
||||
Utils.popen_write("tar", "xf", "-") do |wr|
|
||||
def pipe_to_tar(tool, unpack_dir)
|
||||
path = cached_location
|
||||
|
||||
Utils.popen_read(tool, "-dc", path) do |rd|
|
||||
Utils.popen_write("tar", "xf", "-", "-C", unpack_dir) do |wr|
|
||||
buf = ""
|
||||
wr.write(buf) while rd.read(16384, buf)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# gunzip and bunzip2 write the output file in the same directory as the input
|
||||
# file regardless of the current working directory, so we need to write it to
|
||||
# the correct location ourselves.
|
||||
def buffered_write(tool)
|
||||
target = File.basename(basename_without_params, cached_location.extname)
|
||||
|
||||
Utils.popen_read(tool, "-f", cached_location.to_s, "-c") do |pipe|
|
||||
File.open(target, "wb") do |f|
|
||||
buf = ""
|
||||
f.write(buf) while pipe.read(16384, buf)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def basename_without_params
|
||||
# Strip any ?thing=wad out of .c?thing=wad style extensions
|
||||
File.basename(@url)[/[^?]+/]
|
||||
@ -672,7 +609,7 @@ class SubversionDownloadStrategy < VCSDownloadStrategy
|
||||
|
||||
def stage
|
||||
super
|
||||
quiet_safe_system "svn", "export", "--force", cached_location, Dir.pwd
|
||||
safe_system "svn", "export", "--force", cached_location, Dir.pwd
|
||||
end
|
||||
|
||||
def source_modified_time
|
||||
@ -849,9 +786,9 @@ class GitDownloadStrategy < VCSDownloadStrategy
|
||||
return unless @ref_type == :branch || !ref?
|
||||
|
||||
if !shallow_clone? && shallow_dir?
|
||||
quiet_safe_system "git", "fetch", "origin", "--unshallow"
|
||||
safe_system "git", "fetch", "origin", "--unshallow"
|
||||
else
|
||||
quiet_safe_system "git", "fetch", "origin"
|
||||
safe_system "git", "fetch", "origin"
|
||||
end
|
||||
end
|
||||
|
||||
@ -866,7 +803,7 @@ class GitDownloadStrategy < VCSDownloadStrategy
|
||||
|
||||
def checkout
|
||||
ohai "Checking out #{@ref_type} #{@ref}" if @ref_type && @ref
|
||||
quiet_safe_system "git", "checkout", "-f", @ref, "--"
|
||||
safe_system "git", "checkout", "-f", @ref, "--"
|
||||
end
|
||||
|
||||
def reset_args
|
||||
@ -881,12 +818,12 @@ class GitDownloadStrategy < VCSDownloadStrategy
|
||||
end
|
||||
|
||||
def reset
|
||||
quiet_safe_system "git", *reset_args
|
||||
safe_system "git", *reset_args
|
||||
end
|
||||
|
||||
def update_submodules
|
||||
quiet_safe_system "git", "submodule", "foreach", "--recursive", "git submodule sync"
|
||||
quiet_safe_system "git", "submodule", "update", "--init", "--recursive"
|
||||
safe_system "git", "submodule", "foreach", "--recursive", "git submodule sync"
|
||||
safe_system "git", "submodule", "update", "--init", "--recursive"
|
||||
fix_absolute_submodule_gitdir_references!
|
||||
end
|
||||
|
||||
@ -992,6 +929,10 @@ class CVSDownloadStrategy < VCSDownloadStrategy
|
||||
end
|
||||
end
|
||||
|
||||
def cvspath
|
||||
@cvspath ||= which("cvs", PATH.new("/usr/bin", Formula["cvs"].opt_bin, ENV["PATH"]))
|
||||
end
|
||||
|
||||
def source_modified_time
|
||||
# Filter CVS's files because the timestamp for each of them is the moment
|
||||
# of clone.
|
||||
@ -1045,6 +986,10 @@ class MercurialDownloadStrategy < VCSDownloadStrategy
|
||||
@url = @url.sub(%r{^hg://}, "")
|
||||
end
|
||||
|
||||
def hgpath
|
||||
@hgpath ||= which("hg", PATH.new(Formula["mercurial"].opt_bin, ENV["PATH"]))
|
||||
end
|
||||
|
||||
def stage
|
||||
super
|
||||
|
||||
@ -1082,7 +1027,9 @@ class MercurialDownloadStrategy < VCSDownloadStrategy
|
||||
end
|
||||
|
||||
def update
|
||||
cached_location.cd { quiet_safe_system hgpath, "pull", "--update" }
|
||||
cached_location.cd do
|
||||
safe_system hgpath, "pull", "--update"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1093,6 +1040,10 @@ class BazaarDownloadStrategy < VCSDownloadStrategy
|
||||
ENV["BZR_HOME"] = HOMEBREW_TEMP
|
||||
end
|
||||
|
||||
def bzrpath
|
||||
@bzrpath ||= which("bzr", PATH.new(Formula["bazaar"].opt_bin, ENV["PATH"]))
|
||||
end
|
||||
|
||||
def stage
|
||||
# The export command doesn't work on checkouts
|
||||
# See https://bugs.launchpad.net/bzr/+bug/897511
|
||||
@ -1101,13 +1052,13 @@ class BazaarDownloadStrategy < VCSDownloadStrategy
|
||||
end
|
||||
|
||||
def source_modified_time
|
||||
timestamp = Utils.popen_read("bzr", "log", "-l", "1", "--timezone=utc", cached_location.to_s)[/^timestamp: (.+)$/, 1]
|
||||
timestamp = Utils.popen_read(bzrpath, "log", "-l", "1", "--timezone=utc", cached_location.to_s)[/^timestamp: (.+)$/, 1]
|
||||
raise "Could not get any timestamps from bzr!" if timestamp.to_s.empty?
|
||||
Time.parse timestamp
|
||||
end
|
||||
|
||||
def last_commit
|
||||
Utils.popen_read("bzr", "revno", cached_location.to_s).chomp
|
||||
Utils.popen_read(bzrpath, "revno", cached_location.to_s).chomp
|
||||
end
|
||||
|
||||
private
|
||||
@ -1126,7 +1077,9 @@ class BazaarDownloadStrategy < VCSDownloadStrategy
|
||||
end
|
||||
|
||||
def update
|
||||
cached_location.cd { quiet_safe_system bzrpath, "update" }
|
||||
cached_location.cd do
|
||||
safe_system bzrpath, "update"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1136,6 +1089,10 @@ class FossilDownloadStrategy < VCSDownloadStrategy
|
||||
@url = @url.sub(%r{^fossil://}, "")
|
||||
end
|
||||
|
||||
def fossilpath
|
||||
@fossilpath ||= which("fossil", PATH.new(Formula["fossil"].opt_bin, ENV["PATH"]))
|
||||
end
|
||||
|
||||
def stage
|
||||
super
|
||||
args = [fossilpath, "open", cached_location]
|
||||
@ -1144,11 +1101,11 @@ class FossilDownloadStrategy < VCSDownloadStrategy
|
||||
end
|
||||
|
||||
def source_modified_time
|
||||
Time.parse Utils.popen_read("fossil", "info", "tip", "-R", cached_location.to_s)[/^uuid: +\h+ (.+)$/, 1]
|
||||
Time.parse Utils.popen_read(fossilpath, "info", "tip", "-R", cached_location.to_s)[/^uuid: +\h+ (.+)$/, 1]
|
||||
end
|
||||
|
||||
def last_commit
|
||||
Utils.popen_read("fossil", "info", "tip", "-R", cached_location.to_s)[/^uuid: +(\h+) .+$/, 1]
|
||||
Utils.popen_read(fossilpath, "info", "tip", "-R", cached_location.to_s)[/^uuid: +(\h+) .+$/, 1]
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -147,7 +147,7 @@ module SharedEnvExtension
|
||||
|
||||
# Outputs the current compiler.
|
||||
# @return [Symbol]
|
||||
# <pre># Do something only for clang
|
||||
# <pre># Do something only for the system clang
|
||||
# if ENV.compiler == :clang
|
||||
# # modify CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS in one go:
|
||||
# ENV.append_to_cflags "-I ./missing/includes"
|
||||
@ -301,6 +301,18 @@ module SharedEnvExtension
|
||||
# A no-op until we enable this by default again (which we may never do).
|
||||
def permit_weak_imports; end
|
||||
|
||||
# @private
|
||||
def compiler_any_clang?(cc = compiler)
|
||||
%w[clang llvm_clang].include?(cc.to_s)
|
||||
end
|
||||
|
||||
# @private
|
||||
def compiler_with_cxx11_support?(cc)
|
||||
return if compiler_any_clang?(cc)
|
||||
version = cc[/^gcc-(\d+(?:\.\d+)?)$/, 1]
|
||||
version && Version.create(version) >= Version.create("4.8")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def cc=(val)
|
||||
@ -330,11 +342,6 @@ module SharedEnvExtension
|
||||
return unless homebrew_cc =~ GNU_GCC_REGEXP
|
||||
raise "Non-Apple GCC can't build universal binaries"
|
||||
end
|
||||
|
||||
def gcc_with_cxx11_support?(cc)
|
||||
version = cc[/^gcc-(\d+(?:\.\d+)?)$/, 1]
|
||||
version && Version.create(version) >= Version.create("4.8")
|
||||
end
|
||||
end
|
||||
|
||||
require "extend/os/extend/ENV/shared"
|
||||
|
@ -157,7 +157,7 @@ module Stdenv
|
||||
append_to_cflags Hardware::CPU.universal_archs.as_arch_flags
|
||||
append "LDFLAGS", Hardware::CPU.universal_archs.as_arch_flags
|
||||
|
||||
return if compiler == :clang
|
||||
return if compiler_any_clang?
|
||||
return unless Hardware.is_32_bit?
|
||||
# Can't mix "-march" for a 32-bit CPU with "-arch x86_64"
|
||||
replace_in_cflags(/-march=\S*/, "-Xarch_#{Hardware::CPU.arch_32_bit} \\0")
|
||||
@ -167,7 +167,7 @@ module Stdenv
|
||||
if compiler == :clang
|
||||
append "CXX", "-std=c++11"
|
||||
append "CXX", "-stdlib=libc++"
|
||||
elsif gcc_with_cxx11_support?(compiler)
|
||||
elsif compiler_with_cxx11_support?(compiler)
|
||||
append "CXX", "-std=c++11"
|
||||
else
|
||||
raise "The selected compiler doesn't support C++11: #{compiler}"
|
||||
|
@ -276,7 +276,7 @@ module Superenv
|
||||
self["HOMEBREW_ARCHFLAGS"] = Hardware::CPU.universal_archs.as_arch_flags
|
||||
|
||||
# GCC doesn't accept "-march" for a 32-bit CPU with "-arch x86_64"
|
||||
return if compiler == :clang
|
||||
return if compiler_any_clang?
|
||||
return unless Hardware::CPU.is_32_bit?
|
||||
self["HOMEBREW_OPTFLAGS"] = self["HOMEBREW_OPTFLAGS"].sub(
|
||||
/-march=\S*/,
|
||||
@ -300,7 +300,7 @@ module Superenv
|
||||
if homebrew_cc == "clang"
|
||||
append "HOMEBREW_CCCFG", "x", ""
|
||||
append "HOMEBREW_CCCFG", "g", ""
|
||||
elsif gcc_with_cxx11_support?(homebrew_cc)
|
||||
elsif compiler_with_cxx11_support?(homebrew_cc)
|
||||
append "HOMEBREW_CCCFG", "x", ""
|
||||
else
|
||||
raise "The selected compiler doesn't support C++11: #{homebrew_cc}"
|
||||
|
@ -436,8 +436,12 @@ class FormulaInstaller
|
||||
|
||||
def expand_requirements
|
||||
unsatisfied_reqs = Hash.new { |h, k| h[k] = [] }
|
||||
deps = []
|
||||
req_deps = []
|
||||
formulae = [formula]
|
||||
formula_deps_map = Dependency.expand(formula)
|
||||
.each_with_object({}) do |dep, hash|
|
||||
hash[dep.name] = dep
|
||||
end
|
||||
|
||||
while f = formulae.pop
|
||||
runtime_requirements = runtime_requirements(f)
|
||||
@ -453,6 +457,8 @@ class FormulaInstaller
|
||||
next
|
||||
elsif !runtime_requirements.include?(req) && install_bottle_for_dependent
|
||||
Requirement.prune
|
||||
elsif (dep = formula_deps_map[dependent.name]) && dep.build?
|
||||
Requirement.prune
|
||||
else
|
||||
unsatisfied_reqs[dependent] << req
|
||||
end
|
||||
@ -460,9 +466,9 @@ class FormulaInstaller
|
||||
end
|
||||
|
||||
# Merge the repeated dependencies, which may have different tags.
|
||||
deps = Dependency.merge_repeats(deps)
|
||||
req_deps = Dependency.merge_repeats(req_deps)
|
||||
|
||||
[unsatisfied_reqs, deps]
|
||||
[unsatisfied_reqs, req_deps]
|
||||
end
|
||||
|
||||
def expand_dependencies(deps)
|
||||
|
@ -112,10 +112,10 @@ module Formulary
|
||||
resource = Resource.new(formula_name) { url bottle_name }
|
||||
resource.specs[:bottle] = true
|
||||
downloader = CurlDownloadStrategy.new resource.name, resource
|
||||
@bottle_filename = downloader.cached_location
|
||||
cached = @bottle_filename.exist?
|
||||
cached = downloader.cached_location.exist?
|
||||
downloader.fetch
|
||||
ohai "Pouring the cached bottle" if cached
|
||||
@bottle_filename = downloader.cached_location
|
||||
else
|
||||
@bottle_filename = Pathname(bottle_name).realpath
|
||||
end
|
||||
|
@ -27,12 +27,14 @@ module Homebrew
|
||||
|
||||
def check_development_tools
|
||||
checks = Diagnostic::Checks.new
|
||||
failed = false
|
||||
checks.fatal_development_tools_checks.each do |check|
|
||||
out = checks.send(check)
|
||||
next if out.nil?
|
||||
failed ||= true
|
||||
ofail out
|
||||
end
|
||||
exit 1 if Homebrew.failed?
|
||||
exit 1 if failed
|
||||
end
|
||||
|
||||
def check_cellar
|
||||
|
@ -118,7 +118,7 @@ class Resource
|
||||
if block_given?
|
||||
yield ResourceStageContext.new(self, staging)
|
||||
elsif target
|
||||
target = Pathname.new(target) unless target.is_a? Pathname
|
||||
target = Pathname(target)
|
||||
target.install Pathname.pwd.children
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,3 @@
|
||||
require_relative "./rubocops/bottle_block_cop"
|
||||
require_relative "./rubocops/formula_desc_cop"
|
||||
require_relative "./rubocops/components_order_cop"
|
||||
require_relative "./rubocops/components_redundancy_cop"
|
||||
|
@ -1,29 +0,0 @@
|
||||
require_relative "./extend/formula_cop"
|
||||
|
||||
module RuboCop
|
||||
module Cop
|
||||
module FormulaAuditStrict
|
||||
# This cop audits `bottle` block in Formulae
|
||||
#
|
||||
# - `rebuild` should be used instead of `revision` in `bottle` block
|
||||
|
||||
class BottleBlock < FormulaCop
|
||||
MSG = "Use rebuild instead of revision in bottle block".freeze
|
||||
|
||||
def audit_formula(_node, _class_node, _parent_class_node, body_node)
|
||||
bottle = find_block(body_node, :bottle)
|
||||
return if bottle.nil? || block_size(bottle).zero?
|
||||
problem "Use rebuild instead of revision in bottle block" if method_called_in_block?(bottle, :revision)
|
||||
end
|
||||
|
||||
def autocorrect(node)
|
||||
lambda do |corrector|
|
||||
correction = node.source.sub("revision", "rebuild")
|
||||
corrector.insert_before(node.source_range, correction)
|
||||
corrector.remove(node.source_range)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -8,10 +8,12 @@ module RuboCop
|
||||
# - `url|checksum|mirror` should be inside `stable` block
|
||||
# - `head` and `head do` should not be simultaneously present
|
||||
# - `bottle :unneeded/:disable` and `bottle do` should not be simultaneously present
|
||||
# - `stable do` should not be present without a `head` or `devel` spec
|
||||
|
||||
class ComponentsRedundancy < FormulaCop
|
||||
HEAD_MSG = "`head` and `head do` should not be simultaneously present".freeze
|
||||
BOTTLE_MSG = "`bottle :modifier` and `bottle do` should not be simultaneously present".freeze
|
||||
STABLE_MSG = "`stable do` should not be present without a `head` or `devel` spec".freeze
|
||||
|
||||
def audit_formula(_node, _class_node, _parent_class_node, body_node)
|
||||
stable_block = find_block(body_node, :stable)
|
||||
@ -26,6 +28,11 @@ module RuboCop
|
||||
|
||||
problem BOTTLE_MSG if method_called?(body_node, :bottle) &&
|
||||
find_block(body_node, :bottle)
|
||||
|
||||
return if method_called?(body_node, :head) ||
|
||||
find_block(body_node, :head) ||
|
||||
find_block(body_node, :devel)
|
||||
problem STABLE_MSG if stable_block
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -50,7 +50,6 @@ module RuboCop
|
||||
OPTION = "Formulae should not have an `option`".freeze
|
||||
|
||||
def audit_formula(_node, _class_node, _parent_class_node, body_node)
|
||||
return if versioned_formula?
|
||||
problem DEP_OPTION if method_called_ever?(body_node, :deprecated_option)
|
||||
return unless formula_tap == "homebrew-core"
|
||||
problem OPTION if method_called_ever?(body_node, :option)
|
||||
|
@ -116,6 +116,7 @@ class SystemConfig
|
||||
HOMEBREW_CELLAR: "/usr/local/Cellar",
|
||||
HOMEBREW_CACHE: "#{ENV["HOME"]}/Library/Caches/Homebrew",
|
||||
HOMEBREW_RUBY_WARNINGS: "-W0",
|
||||
HOMEBREW_TEMP: ENV["HOMEBREW_SYSTEM_TEMP"],
|
||||
}.freeze
|
||||
boring_keys = %w[
|
||||
HOMEBREW_BROWSER
|
||||
@ -134,6 +135,7 @@ class SystemConfig
|
||||
HOMEBREW_MACOS_VERSION
|
||||
HOMEBREW_RUBY_PATH
|
||||
HOMEBREW_SYSTEM
|
||||
HOMEBREW_SYSTEM_TEMP
|
||||
HOMEBREW_OS_VERSION
|
||||
HOMEBREW_PATH
|
||||
HOMEBREW_PROCESSOR
|
||||
@ -155,6 +157,9 @@ class SystemConfig
|
||||
if defaults_hash[:HOMEBREW_RUBY_WARNINGS] != ENV["HOMEBREW_RUBY_WARNINGS"].to_s
|
||||
f.puts "HOMEBREW_RUBY_WARNINGS: #{ENV["HOMEBREW_RUBY_WARNINGS"]}"
|
||||
end
|
||||
if defaults_hash[:HOMEBREW_TEMP] != HOMEBREW_TEMP.to_s
|
||||
f.puts "HOMEBREW_TEMP: #{HOMEBREW_TEMP}"
|
||||
end
|
||||
unless ENV["HOMEBREW_ENV"]
|
||||
ENV.sort.each do |key, value|
|
||||
next unless key.start_with?("HOMEBREW_")
|
||||
|
@ -284,8 +284,8 @@ class Tap
|
||||
|
||||
link_completions_and_manpages
|
||||
|
||||
formula_count = formula_files.size
|
||||
puts "Tapped #{Formatter.pluralize(formula_count, "formula")} (#{path.abv})" unless quiet
|
||||
formatted_contents = Formatter.comma_and(*contents)&.prepend(" ")
|
||||
puts "Tapped#{formatted_contents} (#{path.abv})." unless quiet
|
||||
Descriptions.cache_formulae(formula_names)
|
||||
|
||||
return if options[:clone_target]
|
||||
@ -311,15 +311,18 @@ class Tap
|
||||
require "descriptions"
|
||||
raise TapUnavailableError, name unless installed?
|
||||
|
||||
puts "Untapping #{name}... (#{path.abv})"
|
||||
puts "Untapping #{name}..."
|
||||
|
||||
abv = path.abv
|
||||
formatted_contents = Formatter.comma_and(*contents)&.prepend(" ")
|
||||
|
||||
unpin if pinned?
|
||||
formula_count = formula_files.size
|
||||
Descriptions.uncache_formulae(formula_names)
|
||||
Utils::Link.unlink_manpages(path)
|
||||
Utils::Link.unlink_completions(path)
|
||||
path.rmtree
|
||||
path.parent.rmdir_if_possible
|
||||
puts "Untapped #{Formatter.pluralize(formula_count, "formula")}"
|
||||
puts "Untapped#{formatted_contents} (#{abv})."
|
||||
clear_cache
|
||||
end
|
||||
|
||||
@ -343,6 +346,24 @@ class Tap
|
||||
@cask_dir ||= path/"Casks"
|
||||
end
|
||||
|
||||
def contents
|
||||
contents = []
|
||||
|
||||
if (command_count = command_files.count).positive?
|
||||
contents << Formatter.pluralize(command_count, "command")
|
||||
end
|
||||
|
||||
if (cask_count = cask_files.count).positive?
|
||||
contents << Formatter.pluralize(cask_count, "cask")
|
||||
end
|
||||
|
||||
if (formula_count = formula_files.count).positive?
|
||||
contents << Formatter.pluralize(formula_count, "formula")
|
||||
end
|
||||
|
||||
contents
|
||||
end
|
||||
|
||||
# an array of all {Formula} files of this {Tap}.
|
||||
def formula_files
|
||||
@formula_files ||= if formula_dir.directory?
|
||||
@ -427,7 +448,8 @@ class Tap
|
||||
|
||||
# an array of all commands files of this {Tap}.
|
||||
def command_files
|
||||
@command_files ||= Pathname.glob("#{path}/cmd/brew-*").select(&:executable?)
|
||||
@command_files ||= Pathname.glob("#{path}/cmd/brew{,cask}-*")
|
||||
.select { |file| file.executable? || file.extname == ".rb" }
|
||||
end
|
||||
|
||||
# path to the pin record for this {Tap}.
|
||||
|
@ -156,6 +156,18 @@ shared_examples EnvActivation do
|
||||
expect(subject["FOO"]).to eq "bar"
|
||||
end
|
||||
end
|
||||
|
||||
describe "#compiler_any_clang?" do
|
||||
it "returns true for llvm_clang" do
|
||||
expect(subject.compiler_any_clang?(:llvm_clang)).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe "#compiler_with_cxx11_support?" do
|
||||
it "returns true for gcc-4.9" do
|
||||
expect(subject.compiler_with_cxx11_support?("gcc-4.9")).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe Stdenv do
|
||||
|
@ -15,7 +15,7 @@ GEM
|
||||
parallel
|
||||
parser (2.5.1.0)
|
||||
ast (~> 2.4.0)
|
||||
powerpack (0.1.1)
|
||||
powerpack (0.1.2)
|
||||
rainbow (3.0.0)
|
||||
rspec (3.7.0)
|
||||
rspec-core (~> 3.7.0)
|
||||
@ -37,7 +37,7 @@ GEM
|
||||
rspec-support (3.7.1)
|
||||
rspec-wait (0.0.9)
|
||||
rspec (>= 3, < 4)
|
||||
rubocop (0.57.1)
|
||||
rubocop (0.57.2)
|
||||
jaro_winkler (~> 1.5.1)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 2.5)
|
||||
@ -51,7 +51,7 @@ GEM
|
||||
json (>= 1.8, < 3)
|
||||
simplecov-html (~> 0.10.0)
|
||||
simplecov-html (0.10.2)
|
||||
unicode-display_width (1.3.0)
|
||||
unicode-display_width (1.4.0)
|
||||
url (0.3.2)
|
||||
|
||||
PLATFORMS
|
||||
@ -64,8 +64,8 @@ DEPENDENCIES
|
||||
rspec-its
|
||||
rspec-retry
|
||||
rspec-wait
|
||||
rubocop (= 0.57.1)
|
||||
rubocop (= 0.57.2)
|
||||
simplecov
|
||||
|
||||
BUNDLED WITH
|
||||
1.16.1
|
||||
1.16.2
|
||||
|
@ -333,10 +333,10 @@ describe Hbc::Audit, :cask do
|
||||
end
|
||||
end
|
||||
|
||||
describe "GitHub releases appcast check" do
|
||||
let(:appcast_warning) { /Download uses GitHub releases/ }
|
||||
describe "hosting with appcast checks" do
|
||||
let(:appcast_warning) { /please add an appcast/ }
|
||||
|
||||
context "when the download does not use GitHub releases" do
|
||||
context "when the download does not use hosting with an appcast" do
|
||||
let(:cask_token) { "basic-cask" }
|
||||
|
||||
it { is_expected.not_to warn_with(appcast_warning) }
|
||||
@ -353,16 +353,6 @@ describe Hbc::Audit, :cask do
|
||||
|
||||
it { is_expected.to warn_with(appcast_warning) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "SourceForge appcast check" do
|
||||
let(:appcast_warning) { /Download is hosted on SourceForge/ }
|
||||
|
||||
context "when the download is not hosted on SourceForge" do
|
||||
let(:cask_token) { "basic-cask" }
|
||||
|
||||
it { is_expected.not_to warn_with(appcast_warning) }
|
||||
end
|
||||
|
||||
context "when the download is hosted on SourceForge and has an appcast" do
|
||||
let(:cask_token) { "sourceforge-with-appcast" }
|
||||
@ -375,6 +365,30 @@ describe Hbc::Audit, :cask do
|
||||
|
||||
it { is_expected.to warn_with(appcast_warning) }
|
||||
end
|
||||
|
||||
context "when the download is hosted on DevMate and has an appcast" do
|
||||
let(:cask_token) { "devmate-with-appcast" }
|
||||
|
||||
it { is_expected.not_to warn_with(appcast_warning) }
|
||||
end
|
||||
|
||||
context "when the download is hosted on DevMate and does not have an appcast" do
|
||||
let(:cask_token) { "devmate-without-appcast" }
|
||||
|
||||
it { is_expected.to warn_with(appcast_warning) }
|
||||
end
|
||||
|
||||
context "when the download is hosted on HockeyApp and has an appcast" do
|
||||
let(:cask_token) { "hockeyapp-with-appcast" }
|
||||
|
||||
it { is_expected.not_to warn_with(appcast_warning) }
|
||||
end
|
||||
|
||||
context "when the download is hosted on HockeyApp and does not have an appcast" do
|
||||
let(:cask_token) { "hockeyapp-without-appcast" }
|
||||
|
||||
it { is_expected.to warn_with(appcast_warning) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "latest with appcast checks" do
|
||||
|
@ -80,7 +80,7 @@ describe Hbc::SystemCommand, :cask do
|
||||
options.merge!(print_stdout: true)
|
||||
end
|
||||
|
||||
it "echoes both STDOUT and STDERR", :focus do
|
||||
it "echoes both STDOUT and STDERR" do
|
||||
expect { described_class.run(command, options) }
|
||||
.to output("1\n3\n5\n").to_stdout
|
||||
.and output("2\n4\n6\n").to_stderr
|
||||
|
@ -76,4 +76,22 @@ describe Formatter do
|
||||
expect(described_class.pluralize(2, "new formula")).to eq("2 new formulae")
|
||||
end
|
||||
end
|
||||
|
||||
describe "::comma_and" do
|
||||
it "returns nil if given no arguments" do
|
||||
expect(described_class.comma_and).to be nil
|
||||
end
|
||||
|
||||
it "returns the input as string if there is only one argument" do
|
||||
expect(described_class.comma_and(1)).to eq("1")
|
||||
end
|
||||
|
||||
it "concatenates two items with “and”" do
|
||||
expect(described_class.comma_and(1, 2)).to eq("1 and 2")
|
||||
end
|
||||
|
||||
it "concatenates all items with a comma and appends the last with “and”" do
|
||||
expect(described_class.comma_and(1, 2, 3)).to eq("1, 2 and 3")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,47 +0,0 @@
|
||||
require_relative "../../rubocops/bottle_block_cop"
|
||||
|
||||
describe RuboCop::Cop::FormulaAuditStrict::BottleBlock do
|
||||
subject(:cop) { described_class.new }
|
||||
|
||||
context "When auditing Bottle Block" do
|
||||
it "When there is revision in bottle block" do
|
||||
expect_offense(<<~RUBY)
|
||||
class Foo < Formula
|
||||
url 'http://example.com/foo-1.0.tgz'
|
||||
bottle do
|
||||
cellar :any
|
||||
revision 2
|
||||
^^^^^^^^^^ Use rebuild instead of revision in bottle block
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "When auditing Bottle Block with auto correct" do
|
||||
it "When there is revision in bottle block" do
|
||||
source = <<~EOS
|
||||
class Foo < Formula
|
||||
url 'http://example.com/foo-1.0.tgz'
|
||||
bottle do
|
||||
cellar :any
|
||||
revision 2
|
||||
end
|
||||
end
|
||||
EOS
|
||||
|
||||
corrected_source = <<~EOS
|
||||
class Foo < Formula
|
||||
url 'http://example.com/foo-1.0.tgz'
|
||||
bottle do
|
||||
cellar :any
|
||||
rebuild 2
|
||||
end
|
||||
end
|
||||
EOS
|
||||
|
||||
new_source = autocorrect_source(source)
|
||||
expect(new_source).to eq(corrected_source)
|
||||
end
|
||||
end
|
||||
end
|
@ -12,6 +12,10 @@ describe RuboCop::Cop::FormulaAudit::ComponentsRedundancy do
|
||||
stable do
|
||||
# stuff
|
||||
end
|
||||
|
||||
devel do
|
||||
# stuff
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
@ -40,5 +44,45 @@ describe RuboCop::Cop::FormulaAudit::ComponentsRedundancy do
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "When `stable do` is present with a `head` method" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
class Foo < Formula
|
||||
head "http://example.com/foo.git"
|
||||
|
||||
stable do
|
||||
# stuff
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "When `stable do` is present with a `head do` block" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
class Foo < Formula
|
||||
stable do
|
||||
# stuff
|
||||
end
|
||||
|
||||
head do
|
||||
# stuff
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "When `stable do` is present with a `devel` block" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
class Foo < Formula
|
||||
stable do
|
||||
# stuff
|
||||
end
|
||||
|
||||
devel do
|
||||
# stuff
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -0,0 +1,12 @@
|
||||
cask 'devmate-with-appcast' do
|
||||
version '1.0'
|
||||
sha256 'a69e7357bea014f4c14ac9699274f559086844ffa46563c4619bf1addfd72ad9'
|
||||
|
||||
# dl.devmate.com/com.my.fancyapp was verified as official when first introduced to the cask
|
||||
url "https://dl.devmate.com/com.my.fancyapp/app_#{version}.zip"
|
||||
appcast 'https://updates.devmate.com/com.my.fancyapp.app.xml'
|
||||
name 'DevMate'
|
||||
homepage 'http://www.example.com/'
|
||||
|
||||
app 'DevMate.app'
|
||||
end
|
@ -0,0 +1,11 @@
|
||||
cask 'devmate-without-appcast' do
|
||||
version '1.0'
|
||||
sha256 'a69e7357bea014f4c14ac9699274f559086844ffa46563c4619bf1addfd72ad9'
|
||||
|
||||
# dl.devmate.com/com.my.fancyapp was verified as official when first introduced to the cask
|
||||
url "https://dl.devmate.com/com.my.fancyapp/app_#{version}.zip"
|
||||
name 'DevMate'
|
||||
homepage 'http://www.example.com/'
|
||||
|
||||
app 'DevMate.app'
|
||||
end
|
@ -0,0 +1,12 @@
|
||||
cask 'hockeyapp-with-appcast' do
|
||||
version '1.0,123'
|
||||
sha256 'a69e7357bea014f4c14ac9699274f559086844ffa46563c4619bf1addfd72ad9'
|
||||
|
||||
# rink.hockeyapp.net/api/2/apps/67503a7926431872c4b6c1549f5bd6b1 was verified as official when first introduced to the cask
|
||||
url "https://rink.hockeyapp.net/api/2/apps/67503a7926431872c4b6c1549f5bd6b1/app_versions/#{version.after_comma}?format=zip"
|
||||
appcast 'https://rink.hockeyapp.net/api/2/apps/67503a7926431872c4b6c1549f5bd6b1'
|
||||
name 'HockeyApp'
|
||||
homepage 'http://www.example.com/'
|
||||
|
||||
app 'HockeyApp.app'
|
||||
end
|
@ -0,0 +1,11 @@
|
||||
cask 'hockeyapp-without-appcast' do
|
||||
version '1.0,123'
|
||||
sha256 'a69e7357bea014f4c14ac9699274f559086844ffa46563c4619bf1addfd72ad9'
|
||||
|
||||
# rink.hockeyapp.net/api/2/apps/67503a7926431872c4b6c1549f5bd6b1 was verified as official when first introduced to the cask
|
||||
url "https://rink.hockeyapp.net/api/2/apps/67503a7926431872c4b6c1549f5bd6b1/app_versions/#{version.after_comma}?format=zip"
|
||||
name 'HockeyApp'
|
||||
homepage 'http://www.example.com/'
|
||||
|
||||
app 'HockeyApp.app'
|
||||
end
|
@ -14,27 +14,27 @@ end
|
||||
|
||||
# Paths pointing into the Homebrew code base that persist across test runs
|
||||
HOMEBREW_LIBRARY_PATH = Pathname.new(File.expand_path("../../..", __dir__))
|
||||
HOMEBREW_SHIMS_PATH = HOMEBREW_LIBRARY_PATH.parent+"Homebrew/shims"
|
||||
HOMEBREW_SHIMS_PATH = HOMEBREW_LIBRARY_PATH.parent/"Homebrew/shims"
|
||||
HOMEBREW_LOAD_PATH = [
|
||||
File.expand_path(__dir__),
|
||||
HOMEBREW_LIBRARY_PATH,
|
||||
HOMEBREW_LIBRARY_PATH.join("cask/lib"),
|
||||
HOMEBREW_LIBRARY_PATH/"cask/lib",
|
||||
].join(File::PATH_SEPARATOR)
|
||||
|
||||
# Paths redirected to a temporary directory and wiped at the end of the test run
|
||||
HOMEBREW_PREFIX = Pathname.new(TEST_TMPDIR).join("prefix")
|
||||
HOMEBREW_PREFIX = Pathname(TEST_TMPDIR)/"prefix"
|
||||
HOMEBREW_REPOSITORY = HOMEBREW_PREFIX
|
||||
HOMEBREW_LIBRARY = HOMEBREW_REPOSITORY+"Library"
|
||||
HOMEBREW_CACHE = HOMEBREW_PREFIX.parent+"cache"
|
||||
HOMEBREW_CACHE_FORMULA = HOMEBREW_PREFIX.parent+"formula_cache"
|
||||
HOMEBREW_LINKED_KEGS = HOMEBREW_PREFIX.parent+"linked"
|
||||
HOMEBREW_PINNED_KEGS = HOMEBREW_PREFIX.parent+"pinned"
|
||||
HOMEBREW_LOCK_DIR = HOMEBREW_PREFIX.parent+"locks"
|
||||
HOMEBREW_CELLAR = HOMEBREW_PREFIX.parent+"cellar"
|
||||
HOMEBREW_LOGS = HOMEBREW_PREFIX.parent+"logs"
|
||||
HOMEBREW_TEMP = HOMEBREW_PREFIX.parent+"temp"
|
||||
HOMEBREW_LIBRARY = HOMEBREW_REPOSITORY/"Library"
|
||||
HOMEBREW_CACHE = HOMEBREW_PREFIX.parent/"cache"
|
||||
HOMEBREW_CACHE_FORMULA = HOMEBREW_PREFIX.parent/"formula_cache"
|
||||
HOMEBREW_LINKED_KEGS = HOMEBREW_PREFIX.parent/"linked"
|
||||
HOMEBREW_PINNED_KEGS = HOMEBREW_PREFIX.parent/"pinned"
|
||||
HOMEBREW_LOCK_DIR = HOMEBREW_PREFIX.parent/"locks"
|
||||
HOMEBREW_CELLAR = HOMEBREW_PREFIX.parent/"cellar"
|
||||
HOMEBREW_LOGS = HOMEBREW_PREFIX.parent/"logs"
|
||||
HOMEBREW_TEMP = HOMEBREW_PREFIX.parent/"temp"
|
||||
|
||||
TEST_FIXTURE_DIR = HOMEBREW_LIBRARY_PATH.join("test", "support", "fixtures")
|
||||
TEST_FIXTURE_DIR = HOMEBREW_LIBRARY_PATH/"test/support/fixtures"
|
||||
|
||||
TESTBALL_SHA256 = "91e3f7930c98d7ccfb288e115ed52d06b0e5bc16fec7dce8bdda86530027067b".freeze
|
||||
TESTBALL_PATCHES_SHA256 = "799c2d551ac5c3a5759bea7796631a7906a6a24435b52261a317133a0bfb34d9".freeze
|
||||
|
@ -108,4 +108,14 @@ module Formatter
|
||||
|
||||
show_count ? "#{count} #{words}" : words
|
||||
end
|
||||
|
||||
def comma_and(*items)
|
||||
# TODO: Remove when RuboCop 0.57.3 is released.
|
||||
# False positive has been fixed and merged, but is not yet in a
|
||||
# stable release: https://github.com/rubocop-hq/rubocop/pull/6038
|
||||
*items, last = items.map(&:to_s) # rubocop:disable Lint/ShadowedArgument
|
||||
return last if items.empty?
|
||||
|
||||
"#{items.join(", ")} and #{last}"
|
||||
end
|
||||
end
|
||||
|
2
Library/Homebrew/vendor/README.md
vendored
2
Library/Homebrew/vendor/README.md
vendored
@ -3,7 +3,7 @@ Vendored Dependencies
|
||||
|
||||
* [plist](https://github.com/patsplat/plist), version 3.3.0
|
||||
|
||||
* [ruby-macho](https://github.com/Homebrew/ruby-macho), version 1.2.0
|
||||
* [ruby-macho](https://github.com/Homebrew/ruby-macho), version 2.0.0
|
||||
|
||||
* [backports](https://github.com/marcandre/backports), version 3.8.0
|
||||
|
||||
|
22
Library/Homebrew/vendor/macho/macho.rb
vendored
22
Library/Homebrew/vendor/macho/macho.rb
vendored
@ -1,18 +1,18 @@
|
||||
require "#{File.dirname(__FILE__)}/macho/structure"
|
||||
require "#{File.dirname(__FILE__)}/macho/view"
|
||||
require "#{File.dirname(__FILE__)}/macho/headers"
|
||||
require "#{File.dirname(__FILE__)}/macho/load_commands"
|
||||
require "#{File.dirname(__FILE__)}/macho/sections"
|
||||
require "#{File.dirname(__FILE__)}/macho/macho_file"
|
||||
require "#{File.dirname(__FILE__)}/macho/fat_file"
|
||||
require "#{File.dirname(__FILE__)}/macho/exceptions"
|
||||
require "#{File.dirname(__FILE__)}/macho/utils"
|
||||
require "#{File.dirname(__FILE__)}/macho/tools"
|
||||
require_relative "macho/structure"
|
||||
require_relative "macho/view"
|
||||
require_relative "macho/headers"
|
||||
require_relative "macho/load_commands"
|
||||
require_relative "macho/sections"
|
||||
require_relative "macho/macho_file"
|
||||
require_relative "macho/fat_file"
|
||||
require_relative "macho/exceptions"
|
||||
require_relative "macho/utils"
|
||||
require_relative "macho/tools"
|
||||
|
||||
# The primary namespace for ruby-macho.
|
||||
module MachO
|
||||
# release version
|
||||
VERSION = "1.2.0".freeze
|
||||
VERSION = "2.0.0".freeze
|
||||
|
||||
# Opens the given filename as a MachOFile or FatFile, depending on its magic.
|
||||
# @param filename [String] the file being opened
|
||||
|
45
Library/Homebrew/vendor/macho/macho/fat_file.rb
vendored
45
Library/Homebrew/vendor/macho/macho/fat_file.rb
vendored
@ -23,21 +23,37 @@ module MachO
|
||||
# Creates a new FatFile from the given (single-arch) Mach-Os
|
||||
# @param machos [Array<MachOFile>] the machos to combine
|
||||
# @return [FatFile] a new FatFile containing the give machos
|
||||
# @raise [ArgumentError] if less than one Mach-O is given
|
||||
def self.new_from_machos(*machos)
|
||||
header = Headers::FatHeader.new(Headers::FAT_MAGIC, machos.size)
|
||||
raise ArgumentError, "expected at least one Mach-O" if machos.empty?
|
||||
|
||||
# put the smaller alignments further forwards in fat macho, so that we do less padding
|
||||
machos = machos.sort_by(&:segment_alignment)
|
||||
|
||||
bin = +""
|
||||
|
||||
bin << Headers::FatHeader.new(Headers::FAT_MAGIC, machos.size).serialize
|
||||
offset = Headers::FatHeader.bytesize + (machos.size * Headers::FatArch.bytesize)
|
||||
fat_archs = []
|
||||
|
||||
macho_pads = {}
|
||||
macho_bins = {}
|
||||
|
||||
machos.each do |macho|
|
||||
fat_archs << Headers::FatArch.new(macho.header.cputype,
|
||||
macho.header.cpusubtype,
|
||||
offset, macho.serialize.bytesize,
|
||||
macho.alignment)
|
||||
offset += macho.serialize.bytesize
|
||||
macho_offset = Utils.round(offset, 2**macho.segment_alignment)
|
||||
macho_pads[macho] = Utils.padding_for(offset, 2**macho.segment_alignment)
|
||||
macho_bins[macho] = macho.serialize
|
||||
|
||||
bin << Headers::FatArch.new(macho.header.cputype, macho.header.cpusubtype,
|
||||
macho_offset, macho_bins[macho].bytesize,
|
||||
macho.segment_alignment).serialize
|
||||
|
||||
offset += (macho_bins[macho].bytesize + macho_pads[macho])
|
||||
end
|
||||
|
||||
bin = header.serialize
|
||||
bin << fat_archs.map(&:serialize).join
|
||||
bin << machos.map(&:serialize).join
|
||||
machos.each do |macho|
|
||||
bin << Utils.nullpad(macho_pads[macho])
|
||||
bin << macho_bins[macho]
|
||||
end
|
||||
|
||||
new_from_bin(bin)
|
||||
end
|
||||
@ -265,6 +281,15 @@ module MachO
|
||||
File.open(@filename, "wb") { |f| f.write(@raw_data) }
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {FatFile}
|
||||
def to_h
|
||||
{
|
||||
"header" => header.to_h,
|
||||
"fat_archs" => fat_archs.map(&:to_h),
|
||||
"machos" => machos.map(&:to_h),
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Obtain the fat header from raw file data.
|
||||
|
49
Library/Homebrew/vendor/macho/macho/headers.rb
vendored
49
Library/Homebrew/vendor/macho/macho/headers.rb
vendored
@ -475,6 +475,15 @@ module MachO
|
||||
def serialize
|
||||
[magic, nfat_arch].pack(FORMAT)
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {FatHeader}
|
||||
def to_h
|
||||
{
|
||||
"magic" => magic,
|
||||
"magic_sym" => MH_MAGICS[magic],
|
||||
"nfat_arch" => nfat_arch,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# Fat binary header architecture structure. A Fat binary has one or more of
|
||||
@ -508,7 +517,7 @@ module MachO
|
||||
# @api private
|
||||
def initialize(cputype, cpusubtype, offset, size, align)
|
||||
@cputype = cputype
|
||||
@cpusubtype = cpusubtype
|
||||
@cpusubtype = cpusubtype & ~CPU_SUBTYPE_MASK
|
||||
@offset = offset
|
||||
@size = size
|
||||
@align = align
|
||||
@ -518,6 +527,19 @@ module MachO
|
||||
def serialize
|
||||
[cputype, cpusubtype, offset, size, align].pack(FORMAT)
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {FatArch}
|
||||
def to_h
|
||||
{
|
||||
"cputype" => cputype,
|
||||
"cputype_sym" => CPU_TYPES[cputype],
|
||||
"cpusubtype" => cpusubtype,
|
||||
"cpusubtype_sym" => CPU_SUBTYPES[cputype][cpusubtype],
|
||||
"offset" => offset,
|
||||
"size" => size,
|
||||
"align" => align,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# 32-bit Mach-O file header structure
|
||||
@ -639,6 +661,24 @@ module MachO
|
||||
def alignment
|
||||
magic32? ? 4 : 8
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {MachHeader}
|
||||
def to_h
|
||||
{
|
||||
"magic" => magic,
|
||||
"magic_sym" => MH_MAGICS[magic],
|
||||
"cputype" => cputype,
|
||||
"cputype_sym" => CPU_TYPES[cputype],
|
||||
"cpusubtype" => cpusubtype,
|
||||
"cpusubtype_sym" => CPU_SUBTYPES[cputype][cpusubtype],
|
||||
"filetype" => filetype,
|
||||
"filetype_sym" => MH_FILETYPES[filetype],
|
||||
"ncmds" => ncmds,
|
||||
"sizeofcmds" => sizeofcmds,
|
||||
"flags" => flags,
|
||||
"alignment" => alignment,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# 64-bit Mach-O file header structure
|
||||
@ -660,6 +700,13 @@ module MachO
|
||||
super(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags)
|
||||
@reserved = reserved
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {MachHeader64}
|
||||
def to_h
|
||||
{
|
||||
"reserved" => reserved,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
444
Library/Homebrew/vendor/macho/macho/load_commands.rb
vendored
444
Library/Homebrew/vendor/macho/macho/load_commands.rb
vendored
@ -143,7 +143,7 @@ module MachO
|
||||
:LC_LINKER_OPTIMIZATION_HINT => "LinkeditDataCommand",
|
||||
:LC_VERSION_MIN_TVOS => "VersionMinCommand",
|
||||
:LC_VERSION_MIN_WATCHOS => "VersionMinCommand",
|
||||
:LC_NOTE => "LoadCommand",
|
||||
:LC_NOTE => "NoteCommand",
|
||||
:LC_BUILD_VERSION => "BuildVersionCommand",
|
||||
}.freeze
|
||||
|
||||
@ -169,15 +169,16 @@ module MachO
|
||||
:SG_PROTECTED_VERSION_1 => 0x8,
|
||||
}.freeze
|
||||
|
||||
# Mach-O load command structure
|
||||
# This is the most generic load command - only cmd ID and size are
|
||||
# represented, and no actual data. Used when a more specific class
|
||||
# isn't available/implemented.
|
||||
# The top-level Mach-O load command structure.
|
||||
#
|
||||
# This is the most generic load command -- only the type ID and size are
|
||||
# represented. Used when a more specific class isn't available or isn't implemented.
|
||||
class LoadCommand < MachOStructure
|
||||
# @return [MachO::MachOView] the raw view associated with the load command
|
||||
# @return [MachO::MachOView, nil] the raw view associated with the load command,
|
||||
# or nil if the load command was created via {create}.
|
||||
attr_reader :view
|
||||
|
||||
# @return [Integer] the load command's identifying number
|
||||
# @return [Integer] the load command's type ID
|
||||
attr_reader :cmd
|
||||
|
||||
# @return [Integer] the size of the load command, in bytes
|
||||
@ -251,8 +252,8 @@ module MachO
|
||||
view.offset
|
||||
end
|
||||
|
||||
# @return [Symbol] a symbol representation of the load command's
|
||||
# identifying number
|
||||
# @return [Symbol, nil] a symbol representation of the load command's
|
||||
# type ID, or nil if the ID doesn't correspond to a known load command class
|
||||
def type
|
||||
LOAD_COMMANDS[cmd]
|
||||
end
|
||||
@ -265,6 +266,17 @@ module MachO
|
||||
type.to_s
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this load command
|
||||
# @note Children should override this to include additional information.
|
||||
def to_h
|
||||
{
|
||||
"view" => view.to_h,
|
||||
"cmd" => cmd,
|
||||
"cmdsize" => cmdsize,
|
||||
"type" => type,
|
||||
}.merge super
|
||||
end
|
||||
|
||||
# Represents a Load Command string. A rough analogue to the lc_str
|
||||
# struct used internally by OS X. This class allows ruby-macho to
|
||||
# pretend that strings stored in LCs are immediately available without
|
||||
@ -304,6 +316,14 @@ module MachO
|
||||
def to_i
|
||||
@string_offset
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {LCStr}.
|
||||
def to_h
|
||||
{
|
||||
"string" => to_s,
|
||||
"offset" => to_i,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# Represents the contextual information needed by a load command to
|
||||
@ -364,6 +384,14 @@ module MachO
|
||||
|
||||
segs.join("-")
|
||||
end
|
||||
|
||||
# @return [Hash] returns a hash representation of this {UUIDCommand}
|
||||
def to_h
|
||||
{
|
||||
"uuid" => uuid,
|
||||
"uuid_string" => uuid_string,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command indicating that part of this file is to be mapped into
|
||||
@ -398,7 +426,7 @@ module MachO
|
||||
|
||||
# @see MachOStructure::FORMAT
|
||||
# @api private
|
||||
FORMAT = "L=2a16L=4l=2L=2".freeze
|
||||
FORMAT = "L=2Z16L=4l=2L=2".freeze
|
||||
|
||||
# @see MachOStructure::SIZEOF
|
||||
# @api private
|
||||
@ -408,7 +436,7 @@ module MachO
|
||||
def initialize(view, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
|
||||
filesize, maxprot, initprot, nsects, flags)
|
||||
super(view, cmd, cmdsize)
|
||||
@segname = segname.delete("\x00")
|
||||
@segname = segname
|
||||
@vmaddr = vmaddr
|
||||
@vmsize = vmsize
|
||||
@fileoff = fileoff
|
||||
@ -448,6 +476,42 @@ module MachO
|
||||
return false if flag.nil?
|
||||
flags & flag == flag
|
||||
end
|
||||
|
||||
# Guesses the alignment of the segment.
|
||||
# @return [Integer] the guessed alignment, as a power of 2
|
||||
# @note See `guess_align` in `cctools/misc/lipo.c`
|
||||
def guess_align
|
||||
return Sections::MAX_SECT_ALIGN if vmaddr.zero?
|
||||
|
||||
align = 0
|
||||
segalign = 1
|
||||
|
||||
while (segalign & vmaddr).zero?
|
||||
segalign <<= 1
|
||||
align += 1
|
||||
end
|
||||
|
||||
return 2 if align < 2
|
||||
return Sections::MAX_SECT_ALIGN if align > Sections::MAX_SECT_ALIGN
|
||||
|
||||
align
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {SegmentCommand}
|
||||
def to_h
|
||||
{
|
||||
"segname" => segname,
|
||||
"vmaddr" => vmaddr,
|
||||
"vmsize" => vmsize,
|
||||
"fileoff" => fileoff,
|
||||
"filesize" => filesize,
|
||||
"maxprot" => maxprot,
|
||||
"initprot" => initprot,
|
||||
"nsects" => nsects,
|
||||
"flags" => flags,
|
||||
"sections" => sections.map(&:to_h),
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command indicating that part of this file is to be mapped into
|
||||
@ -455,7 +519,7 @@ module MachO
|
||||
class SegmentCommand64 < SegmentCommand
|
||||
# @see MachOStructure::FORMAT
|
||||
# @api private
|
||||
FORMAT = "L=2a16Q=4l=2L=2".freeze
|
||||
FORMAT = "L=2Z16Q=4l=2L=2".freeze
|
||||
|
||||
# @see MachOStructure::SIZEOF
|
||||
# @api private
|
||||
@ -510,6 +574,16 @@ module MachO
|
||||
[cmd, cmdsize, string_offsets[:name], timestamp, current_version,
|
||||
compatibility_version].pack(format) + string_payload
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {DylibCommand}
|
||||
def to_h
|
||||
{
|
||||
"name" => name.to_h,
|
||||
"timestamp" => timestamp,
|
||||
"current_version" => current_version,
|
||||
"compatibility_version" => compatibility_version,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command representing some aspect of the dynamic linker, depending
|
||||
@ -546,6 +620,13 @@ module MachO
|
||||
cmdsize = SIZEOF + string_payload.bytesize
|
||||
[cmd, cmdsize, string_offsets[:name]].pack(format) + string_payload
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {DylinkerCommand}
|
||||
def to_h
|
||||
{
|
||||
"name" => name.to_h,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command used to indicate dynamic libraries used in prebinding.
|
||||
@ -576,6 +657,15 @@ module MachO
|
||||
@nmodules = nmodules
|
||||
@linked_modules = linked_modules
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {PreboundDylibCommand}
|
||||
def to_h
|
||||
{
|
||||
"name" => name.to_h,
|
||||
"nmodules" => nmodules,
|
||||
"linked_modules" => linked_modules,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command used to represent threads.
|
||||
@ -641,6 +731,20 @@ module MachO
|
||||
@reserved5 = reserved5
|
||||
@reserved6 = reserved6
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {RoutinesCommand}
|
||||
def to_h
|
||||
{
|
||||
"init_address" => init_address,
|
||||
"init_module" => init_module,
|
||||
"reserved1" => reserved1,
|
||||
"reserved2" => reserved2,
|
||||
"reserved3" => reserved3,
|
||||
"reserved4" => reserved4,
|
||||
"reserved5" => reserved5,
|
||||
"reserved6" => reserved6,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command containing the address of the dynamic shared library
|
||||
@ -675,6 +779,13 @@ module MachO
|
||||
super(view, cmd, cmdsize)
|
||||
@umbrella = LCStr.new(self, umbrella)
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {SubFrameworkCommand}
|
||||
def to_h
|
||||
{
|
||||
"umbrella" => umbrella.to_h,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command signifying membership of a subumbrella containing the name
|
||||
@ -696,6 +807,13 @@ module MachO
|
||||
super(view, cmd, cmdsize)
|
||||
@sub_umbrella = LCStr.new(self, sub_umbrella)
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {SubUmbrellaCommand}
|
||||
def to_h
|
||||
{
|
||||
"sub_umbrella" => sub_umbrella.to_h,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command signifying a sublibrary of a shared library. Corresponds
|
||||
@ -717,6 +835,13 @@ module MachO
|
||||
super(view, cmd, cmdsize)
|
||||
@sub_library = LCStr.new(self, sub_library)
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {SubLibraryCommand}
|
||||
def to_h
|
||||
{
|
||||
"sub_library" => sub_library.to_h,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command signifying a shared library that is a subframework of
|
||||
@ -738,6 +863,13 @@ module MachO
|
||||
super(view, cmd, cmdsize)
|
||||
@sub_client = LCStr.new(self, sub_client)
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {SubClientCommand}
|
||||
def to_h
|
||||
{
|
||||
"sub_client" => sub_client.to_h,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command containing the offsets and sizes of the link-edit 4.3BSD
|
||||
@ -749,10 +881,10 @@ module MachO
|
||||
# @return [Integer] the number of symbol table entries
|
||||
attr_reader :nsyms
|
||||
|
||||
# @return the string table's offset
|
||||
# @return [Integer] the string table's offset
|
||||
attr_reader :stroff
|
||||
|
||||
# @return the string table size in bytes
|
||||
# @return [Integer] the string table size in bytes
|
||||
attr_reader :strsize
|
||||
|
||||
# @see MachOStructure::FORMAT
|
||||
@ -771,6 +903,16 @@ module MachO
|
||||
@stroff = stroff
|
||||
@strsize = strsize
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {SymtabCommand}
|
||||
def to_h
|
||||
{
|
||||
"symoff" => symoff,
|
||||
"nsyms" => nsyms,
|
||||
"stroff" => stroff,
|
||||
"strsize" => strsize,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command containing symbolic information needed to support data
|
||||
@ -864,6 +1006,30 @@ module MachO
|
||||
@locreloff = locreloff
|
||||
@nlocrel = nlocrel
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {DysymtabCommand}
|
||||
def to_h
|
||||
{
|
||||
"ilocalsym" => ilocalsym,
|
||||
"nlocalsym" => nlocalsym,
|
||||
"iextdefsym" => iextdefsym,
|
||||
"nextdefsym" => nextdefsym,
|
||||
"iundefsym" => iundefsym,
|
||||
"nundefsym" => nundefsym,
|
||||
"tocoff" => tocoff,
|
||||
"ntoc" => ntoc,
|
||||
"modtaboff" => modtaboff,
|
||||
"nmodtab" => nmodtab,
|
||||
"extrefsymoff" => extrefsymoff,
|
||||
"nextrefsyms" => nextrefsyms,
|
||||
"indirectsymoff" => indirectsymoff,
|
||||
"nindirectsyms" => nindirectsyms,
|
||||
"extreloff" => extreloff,
|
||||
"nextrel" => nextrel,
|
||||
"locreloff" => locreloff,
|
||||
"nlocrel" => nlocrel,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command containing the offset and number of hints in the two-level
|
||||
@ -895,6 +1061,15 @@ module MachO
|
||||
@table = TwolevelHintsTable.new(view, htoffset, nhints)
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {TwolevelHintsCommand}
|
||||
def to_h
|
||||
{
|
||||
"htoffset" => htoffset,
|
||||
"nhints" => nhints,
|
||||
"table" => table.hints.map(&:to_h),
|
||||
}.merge super
|
||||
end
|
||||
|
||||
# A representation of the two-level namespace lookup hints table exposed
|
||||
# by a {TwolevelHintsCommand} (`LC_TWOLEVEL_HINTS`).
|
||||
class TwolevelHintsTable
|
||||
@ -927,6 +1102,14 @@ module MachO
|
||||
@isub_image = blob >> 24
|
||||
@itoc = blob & 0x00FFFFFF
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {TwolevelHint}
|
||||
def to_h
|
||||
{
|
||||
"isub_image" => isub_image,
|
||||
"itoc" => itoc,
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -950,6 +1133,13 @@ module MachO
|
||||
super(view, cmd, cmdsize)
|
||||
@cksum = cksum
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {PrebindCksumCommand}
|
||||
def to_h
|
||||
{
|
||||
"cksum" => cksum,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command representing an rpath, which specifies a path that should
|
||||
@ -984,6 +1174,13 @@ module MachO
|
||||
cmdsize = SIZEOF + string_payload.bytesize
|
||||
[cmd, cmdsize, string_offsets[:path]].pack(format) + string_payload
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {RpathCommand}
|
||||
def to_h
|
||||
{
|
||||
"path" => path.to_h,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command representing the offsets and sizes of a blob of data in
|
||||
@ -1011,6 +1208,14 @@ module MachO
|
||||
@dataoff = dataoff
|
||||
@datasize = datasize
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {LinkeditDataCommand}
|
||||
def to_h
|
||||
{
|
||||
"dataoff" => dataoff,
|
||||
"datasize" => datasize,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command representing the offset to and size of an encrypted
|
||||
@ -1040,20 +1245,20 @@ module MachO
|
||||
@cryptsize = cryptsize
|
||||
@cryptid = cryptid
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {EncryptionInfoCommand}
|
||||
def to_h
|
||||
{
|
||||
"cryptoff" => cryptoff,
|
||||
"cryptsize" => cryptsize,
|
||||
"cryptid" => cryptid,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command representing the offset to and size of an encrypted
|
||||
# segment. Corresponds to LC_ENCRYPTION_INFO_64.
|
||||
class EncryptionInfoCommand64 < LoadCommand
|
||||
# @return [Integer] the offset to the encrypted segment
|
||||
attr_reader :cryptoff
|
||||
|
||||
# @return [Integer] the size of the encrypted segment
|
||||
attr_reader :cryptsize
|
||||
|
||||
# @return [Integer] the encryption system, or 0 if not encrypted yet
|
||||
attr_reader :cryptid
|
||||
|
||||
class EncryptionInfoCommand64 < EncryptionInfoCommand
|
||||
# @return [Integer] 64-bit padding value
|
||||
attr_reader :pad
|
||||
|
||||
@ -1067,12 +1272,16 @@ module MachO
|
||||
|
||||
# @api private
|
||||
def initialize(view, cmd, cmdsize, cryptoff, cryptsize, cryptid, pad)
|
||||
super(view, cmd, cmdsize)
|
||||
@cryptoff = cryptoff
|
||||
@cryptsize = cryptsize
|
||||
@cryptid = cryptid
|
||||
super(view, cmd, cmdsize, cryptoff, cryptsize, cryptid)
|
||||
@pad = pad
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {EncryptionInfoCommand64}
|
||||
def to_h
|
||||
{
|
||||
"pad" => pad,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command containing the minimum OS version on which the binary
|
||||
@ -1121,6 +1330,16 @@ module MachO
|
||||
|
||||
segs.join(".")
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {VersionMinCommand}
|
||||
def to_h
|
||||
{
|
||||
"version" => version,
|
||||
"version_string" => version_string,
|
||||
"sdk" => sdk,
|
||||
"sdk_string" => sdk_string,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command containing the minimum OS version on which
|
||||
@ -1156,6 +1375,40 @@ module MachO
|
||||
@tool_entries = ToolEntries.new(view, ntools)
|
||||
end
|
||||
|
||||
# A string representation of the binary's minimum OS version.
|
||||
# @return [String] a string representing the minimum OS version.
|
||||
def minos_string
|
||||
binary = "%032b" % minos
|
||||
segs = [
|
||||
binary[0..15], binary[16..23], binary[24..31]
|
||||
].map { |s| s.to_i(2) }
|
||||
|
||||
segs.join(".")
|
||||
end
|
||||
|
||||
# A string representation of the binary's SDK version.
|
||||
# @return [String] a string representing the SDK version.
|
||||
def sdk_string
|
||||
binary = "%032b" % sdk
|
||||
segs = [
|
||||
binary[0..15], binary[16..23], binary[24..31]
|
||||
].map { |s| s.to_i(2) }
|
||||
|
||||
segs.join(".")
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {BuildVersionCommand}
|
||||
def to_h
|
||||
{
|
||||
"platform" => platform,
|
||||
"minos" => minos,
|
||||
"minos_string" => minos_string,
|
||||
"sdk" => sdk,
|
||||
"sdk_string" => sdk_string,
|
||||
"tool_entries" => tool_entries.tools.map(&:to_h),
|
||||
}.merge super
|
||||
end
|
||||
|
||||
# A representation of the tool versions exposed
|
||||
# by a {BuildVersionCommand} (`LC_BUILD_VERSION`).
|
||||
class ToolEntries
|
||||
@ -1181,37 +1434,23 @@ module MachO
|
||||
# @return [Integer] the tool's version number
|
||||
attr_reader :version
|
||||
|
||||
# @param tool 32-bit integer
|
||||
# # @param version 32-bit integer
|
||||
# @param tool [Integer] 32-bit integer
|
||||
# @param version [Integer] 32-bit integer
|
||||
# @api private
|
||||
def initialize(tool, version)
|
||||
@tool = tool
|
||||
@version = version
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {Tool}
|
||||
def to_h
|
||||
{
|
||||
"tool" => tool,
|
||||
"version" => version,
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# A string representation of the binary's minimum OS version.
|
||||
# @return [String] a string representing the minimum OS version.
|
||||
def minos_string
|
||||
binary = "%032b" % minos
|
||||
segs = [
|
||||
binary[0..15], binary[16..23], binary[24..31]
|
||||
].map { |s| s.to_i(2) }
|
||||
|
||||
segs.join(".")
|
||||
end
|
||||
|
||||
# A string representation of the binary's SDK version.
|
||||
# @return [String] a string representing the SDK version.
|
||||
def sdk_string
|
||||
binary = "%032b" % sdk
|
||||
segs = [
|
||||
binary[0..15], binary[16..23], binary[24..31]
|
||||
].map { |s| s.to_i(2) }
|
||||
|
||||
segs.join(".")
|
||||
end
|
||||
end
|
||||
|
||||
# A load command containing the file offsets and sizes of the new
|
||||
@ -1272,6 +1511,22 @@ module MachO
|
||||
@export_off = export_off
|
||||
@export_size = export_size
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {DyldInfoCommand}
|
||||
def to_h
|
||||
{
|
||||
"rebase_off" => rebase_off,
|
||||
"rebase_size" => rebase_size,
|
||||
"bind_off" => bind_off,
|
||||
"bind_size" => bind_size,
|
||||
"weak_bind_off" => weak_bind_off,
|
||||
"weak_bind_size" => weak_bind_size,
|
||||
"lazy_bind_off" => lazy_bind_off,
|
||||
"lazy_bind_size" => lazy_bind_size,
|
||||
"export_off" => export_off,
|
||||
"export_size" => export_size,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command containing linker options embedded in object files.
|
||||
@ -1293,6 +1548,13 @@ module MachO
|
||||
super(view, cmd, cmdsize)
|
||||
@count = count
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {LinkerOptionCommand}
|
||||
def to_h
|
||||
{
|
||||
"count" => count,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command specifying the offset of main(). Corresponds to LC_MAIN.
|
||||
@ -1317,6 +1579,14 @@ module MachO
|
||||
@entryoff = entryoff
|
||||
@stacksize = stacksize
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {EntryPointCommand}
|
||||
def to_h
|
||||
{
|
||||
"entryoff" => entryoff,
|
||||
"stacksize" => stacksize,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command specifying the version of the sources used to build the
|
||||
@ -1350,6 +1620,14 @@ module MachO
|
||||
|
||||
segs.join(".")
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {SourceVersionCommand}
|
||||
def to_h
|
||||
{
|
||||
"version" => version,
|
||||
"version_string" => version_string,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# An obsolete load command containing the offset and size of the (GNU style)
|
||||
@ -1375,6 +1653,14 @@ module MachO
|
||||
@offset = offset
|
||||
@size = size
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {SymsegCommand}
|
||||
def to_h
|
||||
{
|
||||
"offset" => offset,
|
||||
"size" => size,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# An obsolete load command containing a free format string table. Each
|
||||
@ -1412,6 +1698,14 @@ module MachO
|
||||
@name = LCStr.new(self, name)
|
||||
@header_addr = header_addr
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {FvmfileCommand}
|
||||
def to_h
|
||||
{
|
||||
"name" => name.to_h,
|
||||
"header_addr" => header_addr,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# An obsolete load command containing the path to a library to be loaded
|
||||
@ -1440,6 +1734,52 @@ module MachO
|
||||
@minor_version = minor_version
|
||||
@header_addr = header_addr
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {FvmlibCommand}
|
||||
def to_h
|
||||
{
|
||||
"name" => name.to_h,
|
||||
"minor_version" => minor_version,
|
||||
"header_addr" => header_addr,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# A load command containing an owner name and offset/size for an arbitrary data region.
|
||||
# Corresponds to LC_NOTE.
|
||||
class NoteCommand < LoadCommand
|
||||
# @return [String] the name of the owner for this note
|
||||
attr_reader :data_owner
|
||||
|
||||
# @return [Integer] the offset, within the file, of the note
|
||||
attr_reader :offset
|
||||
|
||||
# @return [Integer] the size, in bytes, of the note
|
||||
attr_reader :size
|
||||
|
||||
# @see MachOStructure::FORMAT
|
||||
# @api private
|
||||
FORMAT = "L=2Z16Q=2".freeze
|
||||
|
||||
# @see MachOStructure::SIZEOF
|
||||
# @api private
|
||||
SIZEOF = 48
|
||||
|
||||
def initialize(view, cmd, cmdsize, data_owner, offset, size)
|
||||
super(view, cmd, cmdsize)
|
||||
@data_owner = data_owner
|
||||
@offset = offset
|
||||
@size = size
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {NoteCommand}
|
||||
def to_h
|
||||
{
|
||||
"data_owner" => data_owner,
|
||||
"offset" => offset,
|
||||
"size" => size,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -25,7 +25,7 @@ module MachO
|
||||
# @note load commands are provided in order of ascending offset.
|
||||
attr_reader :load_commands
|
||||
|
||||
# Creates a new MachOFile instance from a binary string.
|
||||
# Creates a new instance from a binary string.
|
||||
# @param bin [String] a binary string containing raw Mach-O data
|
||||
# @return [MachOFile] a new MachOFile
|
||||
def self.new_from_bin(bin)
|
||||
@ -35,7 +35,7 @@ module MachO
|
||||
instance
|
||||
end
|
||||
|
||||
# Creates a new FatFile from the given filename.
|
||||
# Creates a new instance from data read from the given filename.
|
||||
# @param filename [String] the Mach-O file to load from
|
||||
# @raise [ArgumentError] if the given file does not exist
|
||||
def initialize(filename)
|
||||
@ -219,8 +219,7 @@ module MachO
|
||||
update_sizeofcmds(sizeofcmds - lc.cmdsize)
|
||||
|
||||
# pad the space after the load commands to preserve offsets
|
||||
null_pad = "\x00" * lc.cmdsize
|
||||
@raw_data.insert(header.class.bytesize + sizeofcmds - lc.cmdsize, null_pad)
|
||||
@raw_data.insert(header.class.bytesize + sizeofcmds - lc.cmdsize, Utils.nullpad(lc.cmdsize))
|
||||
|
||||
populate_fields if options.fetch(:repopulate, true)
|
||||
end
|
||||
@ -252,6 +251,33 @@ module MachO
|
||||
end
|
||||
end
|
||||
|
||||
# The segment alignment for the Mach-O. Guesses conservatively.
|
||||
# @return [Integer] the alignment, as a power of 2
|
||||
# @note This is **not** the same as {#alignment}!
|
||||
# @note See `get_align` and `get_align_64` in `cctools/misc/lipo.c`
|
||||
def segment_alignment
|
||||
# special cases: 12 for x86/64/PPC/PP64, 14 for ARM/ARM64
|
||||
return 12 if %i[i386 x86_64 ppc ppc64].include?(cputype)
|
||||
return 14 if %i[arm arm64].include?(cputype)
|
||||
|
||||
cur_align = Sections::MAX_SECT_ALIGN
|
||||
|
||||
segments.each do |segment|
|
||||
if filetype == :object
|
||||
# start with the smallest alignment, and work our way up
|
||||
align = magic32? ? 2 : 3
|
||||
segment.sections.each do |section|
|
||||
align = section.align unless section.align <= align
|
||||
end
|
||||
else
|
||||
align = segment.guess_align
|
||||
end
|
||||
cur_align = align if align < cur_align
|
||||
end
|
||||
|
||||
cur_align
|
||||
end
|
||||
|
||||
# The Mach-O's dylib ID, or `nil` if not a dylib.
|
||||
# @example
|
||||
# file.dylib_id # => 'libBar.dylib'
|
||||
@ -408,6 +434,14 @@ module MachO
|
||||
File.open(@filename, "wb") { |f| f.write(@raw_data) }
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {MachOFile}
|
||||
def to_h
|
||||
{
|
||||
"header" => header.to_h,
|
||||
"load_commands" => load_commands.map(&:to_h),
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# The file's Mach-O header structure.
|
||||
|
42
Library/Homebrew/vendor/macho/macho/sections.rb
vendored
42
Library/Homebrew/vendor/macho/macho/sections.rb
vendored
@ -13,6 +13,10 @@ module MachO
|
||||
# system settable attributes mask
|
||||
SECTION_ATTRIBUTES_SYS = 0x00ffff00
|
||||
|
||||
# maximum specifiable section alignment, as a power of 2
|
||||
# @note see `MAXSECTALIGN` macro in `cctools/misc/lipo.c`
|
||||
MAX_SECT_ALIGN = 15
|
||||
|
||||
# association of section flag symbols to values
|
||||
# @api private
|
||||
SECTION_FLAGS = {
|
||||
@ -104,7 +108,7 @@ module MachO
|
||||
attr_reader :reserved2
|
||||
|
||||
# @see MachOStructure::FORMAT
|
||||
FORMAT = "a16a16L=9".freeze
|
||||
FORMAT = "Z16Z16L=9".freeze
|
||||
|
||||
# @see MachOStructure::SIZEOF
|
||||
SIZEOF = 68
|
||||
@ -125,16 +129,14 @@ module MachO
|
||||
@reserved2 = reserved2
|
||||
end
|
||||
|
||||
# @return [String] the section's name, with any trailing NULL characters
|
||||
# removed
|
||||
# @return [String] the section's name
|
||||
def section_name
|
||||
sectname.delete("\x00")
|
||||
sectname
|
||||
end
|
||||
|
||||
# @return [String] the parent segment's name, with any trailing NULL
|
||||
# characters removed
|
||||
# @return [String] the parent segment's name
|
||||
def segment_name
|
||||
segname.delete("\x00")
|
||||
segname
|
||||
end
|
||||
|
||||
# @return [Boolean] whether the section is empty (i.e, {size} is 0)
|
||||
@ -151,6 +153,23 @@ module MachO
|
||||
return false if flag.nil?
|
||||
flags & flag == flag
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {Section}
|
||||
def to_h
|
||||
{
|
||||
"sectname" => sectname,
|
||||
"segname" => segname,
|
||||
"addr" => addr,
|
||||
"size" => size,
|
||||
"offset" => offset,
|
||||
"align" => align,
|
||||
"reloff" => reloff,
|
||||
"nreloc" => nreloc,
|
||||
"flags" => flags,
|
||||
"reserved1" => reserved1,
|
||||
"reserved2" => reserved2,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
|
||||
# Represents a section of a segment for 64-bit architectures.
|
||||
@ -159,7 +178,7 @@ module MachO
|
||||
attr_reader :reserved3
|
||||
|
||||
# @see MachOStructure::FORMAT
|
||||
FORMAT = "a16a16Q=2L=8".freeze
|
||||
FORMAT = "Z16Z16Q=2L=8".freeze
|
||||
|
||||
# @see MachOStructure::SIZEOF
|
||||
SIZEOF = 80
|
||||
@ -171,6 +190,13 @@ module MachO
|
||||
nreloc, flags, reserved1, reserved2)
|
||||
@reserved3 = reserved3
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {Section64}
|
||||
def to_h
|
||||
{
|
||||
"reserved3" => reserved3,
|
||||
}.merge super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
10
Library/Homebrew/vendor/macho/macho/structure.rb
vendored
10
Library/Homebrew/vendor/macho/macho/structure.rb
vendored
@ -26,5 +26,15 @@ module MachO
|
||||
|
||||
new(*bin.unpack(format))
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {MachOStructure}.
|
||||
def to_h
|
||||
{
|
||||
"structure" => {
|
||||
"format" => self.class::FORMAT,
|
||||
"bytesize" => self.class.bytesize,
|
||||
},
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
14
Library/Homebrew/vendor/macho/macho/utils.rb
vendored
14
Library/Homebrew/vendor/macho/macho/utils.rb
vendored
@ -22,6 +22,16 @@ module MachO
|
||||
round(size, alignment) - size
|
||||
end
|
||||
|
||||
# Returns a string of null bytes of the requested (non-negative) size
|
||||
# @param size [Integer] the size of the nullpad
|
||||
# @return [String] the null string (or empty string, for `size = 0`)
|
||||
# @raise [ArgumentError] if a non-positive nullpad is requested
|
||||
def self.nullpad(size)
|
||||
raise ArgumentError, "size < 0: #{size}" if size.negative?
|
||||
|
||||
"\x00" * size
|
||||
end
|
||||
|
||||
# Converts an abstract (native-endian) String#unpack format to big or
|
||||
# little.
|
||||
# @param format [String] the format string being converted
|
||||
@ -46,11 +56,11 @@ module MachO
|
||||
strings.each do |key, string|
|
||||
offsets[key] = next_offset
|
||||
payload << string
|
||||
payload << "\x00"
|
||||
payload << Utils.nullpad(1)
|
||||
next_offset += string.bytesize + 1
|
||||
end
|
||||
|
||||
payload << "\x00" * padding_for(fixed_offset + payload.bytesize, alignment)
|
||||
payload << Utils.nullpad(padding_for(fixed_offset + payload.bytesize, alignment))
|
||||
[payload, offsets]
|
||||
end
|
||||
|
||||
|
8
Library/Homebrew/vendor/macho/macho/view.rb
vendored
8
Library/Homebrew/vendor/macho/macho/view.rb
vendored
@ -19,5 +19,13 @@ module MachO
|
||||
@endianness = endianness
|
||||
@offset = offset
|
||||
end
|
||||
|
||||
# @return [Hash] a hash representation of this {MachOView}.
|
||||
def to_h
|
||||
{
|
||||
"endianness" => endianness,
|
||||
"offset" => offset,
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -26,10 +26,10 @@ GEM
|
||||
execjs (2.7.0)
|
||||
faraday (0.15.2)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.9.23)
|
||||
ffi (1.9.25)
|
||||
forwardable-extended (2.6.0)
|
||||
gemoji (3.0.0)
|
||||
github-pages (186)
|
||||
github-pages (187)
|
||||
activesupport (= 4.2.10)
|
||||
github-pages-health-check (= 1.8.1)
|
||||
jekyll (= 3.7.3)
|
||||
@ -48,7 +48,7 @@ GEM
|
||||
jekyll-relative-links (= 0.5.3)
|
||||
jekyll-remote-theme (= 0.3.1)
|
||||
jekyll-sass-converter (= 1.5.2)
|
||||
jekyll-seo-tag (= 2.4.0)
|
||||
jekyll-seo-tag (= 2.5.0)
|
||||
jekyll-sitemap (= 1.2.0)
|
||||
jekyll-swiss (= 0.4.0)
|
||||
jekyll-theme-architect (= 0.1.1)
|
||||
@ -80,7 +80,7 @@ GEM
|
||||
octokit (~> 4.0)
|
||||
public_suffix (~> 2.0)
|
||||
typhoeus (~> 1.3)
|
||||
html-pipeline (2.8.0)
|
||||
html-pipeline (2.8.3)
|
||||
activesupport (>= 2)
|
||||
nokogiri (>= 1.4)
|
||||
http_parser.rb (0.6.0)
|
||||
@ -138,7 +138,7 @@ GEM
|
||||
rubyzip (>= 1.2.1, < 3.0)
|
||||
jekyll-sass-converter (1.5.2)
|
||||
sass (~> 3.4)
|
||||
jekyll-seo-tag (2.4.0)
|
||||
jekyll-seo-tag (2.5.0)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-sitemap (1.2.0)
|
||||
jekyll (~> 3.3)
|
||||
@ -206,7 +206,7 @@ GEM
|
||||
jekyll-seo-tag (~> 2.1)
|
||||
minitest (5.11.3)
|
||||
multipart-post (2.0.0)
|
||||
nokogiri (1.8.2)
|
||||
nokogiri (1.8.3)
|
||||
mini_portile2 (~> 2.3.0)
|
||||
octokit (4.9.0)
|
||||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
@ -237,7 +237,7 @@ GEM
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (1.2.5)
|
||||
thread_safe (~> 0.1)
|
||||
unicode-display_width (1.3.3)
|
||||
unicode-display_width (1.4.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
Loading…
x
Reference in New Issue
Block a user