582 lines
20 KiB
Ruby
Raw Normal View History

2020-10-10 14:16:11 +02:00
# typed: false
# frozen_string_literal: true
require "formula"
2016-04-25 17:57:51 +01:00
require "utils/bottles"
require "tab"
require "keg"
require "formula_versions"
2019-04-17 18:25:08 +09:00
require "cli/parser"
require "utils/inreplace"
require "erb"
BOTTLE_ERB = <<-EOS
2013-09-21 21:21:42 +01:00
bottle do
<% if root_url != "#{HOMEBREW_BOTTLE_DEFAULT_DOMAIN}/bottles" %>
root_url "<%= root_url %>"
<% end %>
<% if ![HOMEBREW_DEFAULT_PREFIX,
HOMEBREW_MACOS_ARM_DEFAULT_PREFIX,
HOMEBREW_LINUX_DEFAULT_PREFIX].include?(prefix) %>
2014-01-18 21:40:52 +00:00
prefix "<%= prefix %>"
2013-09-21 21:21:42 +01:00
<% end %>
<% if cellar.is_a? Symbol %>
cellar :<%= cellar %>
bottle merge: add support for linux cellar The first attempt to build and pull a formula (hello) for linux in homebrew-core resulted in a wrong cellar line being added to the formula's bottle block. How to test/debug this, using the 4 bottles that where built for hello: brew bottle --merge --debug hello--2.10_1.mojave.bottle.json hello--2.10_1.x86_64_linux.bottle.json hello--2.10_1.big_sur.bottle.json hello--2.10_1.catalina.bottle.json This command would add create the following bottle block: bottle do cellar "/home/linuxbrew/.linuxbrew/Cellar" sha256 "a0af7dcbb5c83f6f3f7ecd507c2d352c1a018f894d51ad241ce8492fa598010f" => :big_sur sha256 "5334dd344986e46b2aa4f0471cac7b0914bd7de7cb890a34415771788d03f2ac" => :catalina sha256 "22948764d8f8d7be4870ff92dae64d986eb63a9150b219c20fff87d1a6aa93d6" => :mojave sha256 "702dc7f78444d2f4f1c19324be654bcbb8b99dd0e9ce26c3e2fbc3b6464a189f" => :x86_64_linux end After the change in this PR, the result is the following: bottle do sha256 "a0af7dcbb5c83f6f3f7ecd507c2d352c1a018f894d51ad241ce8492fa598010f" => :big_sur sha256 "5334dd344986e46b2aa4f0471cac7b0914bd7de7cb890a34415771788d03f2ac" => :catalina sha256 "22948764d8f8d7be4870ff92dae64d986eb63a9150b219c20fff87d1a6aa93d6" => :mojave sha256 "702dc7f78444d2f4f1c19324be654bcbb8b99dd0e9ce26c3e2fbc3b6464a189f" => :x86_64_linux end The brew bottle --merge code will pick the most common cellar line between the 4 bottles, by order of priority: - non-relocatable (fixed cellar path) - cellar :any - cellar :any_skip_relocation In the case of the hello bottle, the 3 mac bottles are "cellar :any_skip_relocation", and the linux bottle is non-relocatable. So the linux bottle wins and the code correctly determines that the 4 bottles should be non-relocatable. In that case, the /home/linuxbrew/.linuxbrew/Cellar path is defined as cellar, and by convention we do not write that out to the formula file, hence the cellar path check that needs to be modified in this PR. This PR also fixes the same situation for mac ARM cellar paths
2020-11-26 14:29:42 +01:00
<% elsif ![Homebrew::DEFAULT_MACOS_CELLAR,
Homebrew::DEFAULT_MACOS_ARM_CELLAR,
Homebrew::DEFAULT_LINUX_CELLAR].include?(cellar) %>
2014-01-18 21:40:52 +00:00
cellar "<%= cellar %>"
2013-09-21 21:21:42 +01:00
<% end %>
2017-09-24 20:12:58 +01:00
<% if rebuild.positive? %>
2016-08-18 17:32:35 +01:00
rebuild <%= rebuild %>
2013-09-21 21:21:42 +01:00
<% end %>
2013-09-23 17:30:47 +01:00
<% checksums.each do |checksum_type, checksum_values| %>
<% checksum_values.each do |checksum_value| %>
<% checksum, macos = checksum_value.shift %>
<%= checksum_type %> "<%= checksum %>" => :<%= macos %>
2013-09-21 21:21:42 +01:00
<% end %>
2013-09-23 17:30:47 +01:00
<% end %>
2013-09-21 21:21:42 +01:00
end
EOS
MAXIMUM_STRING_MATCHES = 100
module Homebrew
2020-10-20 12:03:48 +02:00
extend T::Sig
2016-09-26 01:44:51 +02:00
module_function
2020-10-20 12:03:48 +02:00
sig { returns(CLI::Parser) }
def bottle_args
Homebrew::CLI::Parser.new do
usage_banner <<~EOS
`bottle` [<options>] <formula>
2018-09-28 21:39:52 +05:30
Generate a bottle (binary package) from a formula that was installed with
2018-09-28 21:39:52 +05:30
`--build-bottle`.
If the formula specifies a rebuild version, it will be incremented in the
generated DSL. Passing `--keep-old` will attempt to keep it at its original
value, while `--no-rebuild` will remove it.
2018-09-28 21:39:52 +05:30
EOS
switch "--skip-relocation",
2019-04-30 08:44:35 +01:00
description: "Do not check if the bottle can be marked as relocatable."
2018-09-28 21:39:52 +05:30
switch "--force-core-tap",
2019-04-30 08:44:35 +01:00
description: "Build a bottle even if <formula> is not in `homebrew/core` or any installed taps."
2018-09-28 21:39:52 +05:30
switch "--no-rebuild",
2019-04-30 08:44:35 +01:00
description: "If the formula specifies a rebuild version, remove it from the generated DSL."
2018-09-28 21:39:52 +05:30
switch "--keep-old",
2019-04-30 08:44:35 +01:00
description: "If the formula specifies a rebuild version, attempt to preserve its value in the "\
"generated DSL."
switch "--json",
description: "Write bottle information to a JSON file, which can be used as the value for "\
2019-04-30 08:44:35 +01:00
"`--merge`."
2018-09-28 21:39:52 +05:30
switch "--merge",
2019-04-30 08:44:35 +01:00
description: "Generate an updated bottle block for a formula and optionally merge it into the "\
"formula file. Instead of a formula name, requires the path to a JSON file generated with "\
2019-04-30 08:44:35 +01:00
"`brew bottle --json` <formula>."
2018-09-28 21:39:52 +05:30
switch "--write",
2019-04-30 08:44:35 +01:00
depends_on: "--merge",
description: "Write changes to the formula file. A new commit will be generated unless "\
2019-04-30 08:44:35 +01:00
"`--no-commit` is passed."
2018-09-28 21:39:52 +05:30
switch "--no-commit",
2019-04-30 08:44:35 +01:00
depends_on: "--write",
description: "When passed with `--write`, a new commit will not generated after writing changes "\
"to the formula file."
flag "--root-url=",
2019-04-30 08:44:35 +01:00
description: "Use the specified <URL> as the root of the bottle's URL instead of Homebrew's default."
2020-07-30 18:40:10 +02:00
conflicts "--no-rebuild", "--keep-old"
min_named 1
2018-03-25 12:22:29 +05:30
end
end
def bottle
2020-07-30 18:40:10 +02:00
args = bottle_args.parse
2018-03-25 12:22:29 +05:30
return merge(args: args) if args.merge?
2018-09-17 02:45:00 +02:00
ensure_relocation_formulae_installed! unless args.skip_relocation?
args.named.to_resolved_formulae.each do |f|
bottle_formula f, args: args
2018-03-25 12:22:29 +05:30
end
end
def ensure_relocation_formulae_installed!
Keg.relocation_formulae.each do |f|
next if Formula[f].latest_version_installed?
2018-09-17 02:45:00 +02:00
ohai "Installing #{f}..."
safe_system HOMEBREW_BREW_FILE, "install", f
end
end
def keg_contain?(string, keg, ignores, formula_and_runtime_deps_names = nil, args:)
@put_string_exists_header, @put_filenames = nil
2015-02-26 19:13:10 +00:00
print_filename = lambda do |str, filename|
2015-02-26 19:13:10 +00:00
unless @put_string_exists_header
opoo "String '#{str}' still exists in these files:"
2015-02-26 19:13:10 +00:00
@put_string_exists_header = true
end
2015-02-26 19:13:10 +00:00
@put_filenames ||= []
2016-09-22 20:12:28 +02:00
return if @put_filenames.include?(filename)
2016-09-22 20:12:28 +02:00
2016-08-30 21:38:13 +02:00
puts Formatter.error(filename.to_s)
2016-09-22 20:12:28 +02:00
@put_filenames << filename
end
result = false
keg.each_unique_file_matching(string) do |file|
next if Metafiles::EXTENSIONS.include?(file.extname) # Skip document files.
linked_libraries = Keg.file_linked_libraries(file, string)
result ||= !linked_libraries.empty?
if args.verbose?
print_filename.call(string, file) unless linked_libraries.empty?
linked_libraries.each do |lib|
2016-10-02 08:40:38 +02:00
puts " #{Tty.bold}-->#{Tty.reset} links to #{lib}"
end
end
text_matches = []
# Use strings to search through the file for each string
Utils.popen_read("strings", "-t", "x", "-", file.to_s) do |io|
until io.eof?
str = io.readline.chomp
next if ignores.any? { |i| i =~ str }
next unless str.include? string
2018-09-17 02:45:00 +02:00
offset, match = str.split(" ", 2)
next if linked_libraries.include? match # Don't bother reporting a string if it was found by otool
# Do not report matches to files that do not exist.
next unless File.exist? match
# Do not report matches to build dependencies.
if formula_and_runtime_deps_names.present?
begin
keg_name = Keg.for(Pathname.new(match)).name
next unless formula_and_runtime_deps_names.include? keg_name
rescue NotAKegError
nil
end
end
result = true
text_matches << [match, offset]
end
end
next unless args.verbose? && !text_matches.empty?
2018-09-17 02:45:00 +02:00
print_filename.call(string, file)
2016-09-11 17:41:51 +01:00
text_matches.first(MAXIMUM_STRING_MATCHES).each do |match, offset|
2016-10-02 08:40:38 +02:00
puts " #{Tty.bold}-->#{Tty.reset} match '#{match}' at offset #{Tty.bold}0x#{offset}#{Tty.reset}"
2016-09-11 17:41:51 +01:00
end
2016-09-11 17:41:51 +01:00
if text_matches.size > MAXIMUM_STRING_MATCHES
2019-11-29 14:53:01 -05:00
puts "Only the first #{MAXIMUM_STRING_MATCHES} matches were output."
end
end
2020-08-01 14:56:11 -04:00
keg_contain_absolute_symlink_starting_with?(string, keg, args: args) || result
2016-07-26 21:50:00 -07:00
end
2020-08-01 14:56:11 -04:00
def keg_contain_absolute_symlink_starting_with?(string, keg, args:)
absolute_symlinks_start_with_string = []
keg.find do |pn|
2016-09-11 17:41:51 +01:00
next unless pn.symlink? && (link = pn.readlink).absolute?
2018-09-17 02:45:00 +02:00
2016-09-23 11:01:40 +02:00
absolute_symlinks_start_with_string << pn if link.to_s.start_with?(string)
end
2020-09-01 14:05:52 +01:00
if args.verbose? && absolute_symlinks_start_with_string.present?
opoo "Absolute symlink starting with #{string}:"
absolute_symlinks_start_with_string.each do |pn|
puts " #{pn} -> #{pn.resolved_path}"
end
end
!absolute_symlinks_start_with_string.empty?
end
def bottle_output(bottle)
2013-09-21 21:21:42 +01:00
erb = ERB.new BOTTLE_ERB
erb.result(bottle.instance_eval { binding }).gsub(/^\s*$\n/, "")
end
def sudo_purge
return unless ENV["HOMEBREW_BOTTLE_SUDO_PURGE"]
system "/usr/bin/sudo", "--non-interactive", "/usr/sbin/purge"
end
def bottle_formula(f, args:)
return ofail "Formula not installed or up-to-date: #{f.full_name}" unless f.latest_version_installed?
unless tap = f.tap
return ofail "Formula not from core or any installed taps: #{f.full_name}" unless args.force_core_tap?
2016-09-22 20:12:28 +02:00
tap = CoreTap.instance
end
2015-09-14 20:06:27 +08:00
if f.bottle_disabled?
ofail "Formula has disabled bottle: #{f.full_name}"
puts f.bottle_disable_reason
return
end
return ofail "Formula was not installed with --build-bottle: #{f.full_name}" unless Utils::Bottles.built_as? f
2016-09-23 11:01:40 +02:00
return ofail "Formula has no stable version: #{f.full_name}" unless f.stable
if args.no_rebuild? || !f.tap
2016-08-18 17:32:35 +01:00
rebuild = 0
elsif args.keep_old?
2016-08-18 17:32:35 +01:00
rebuild = f.bottle_specification.rebuild
else
2016-08-18 17:32:35 +01:00
ohai "Determining #{f.full_name} bottle rebuild..."
versions = FormulaVersions.new(f)
2016-08-18 17:32:35 +01:00
rebuilds = versions.bottle_version_map("origin/master")[f.pkg_version]
2017-09-24 20:12:58 +01:00
rebuilds.pop if rebuilds.last.to_i.positive?
2016-08-18 17:32:35 +01:00
rebuild = rebuilds.empty? ? 0 : rebuilds.max.to_i + 1
end
2016-08-18 17:32:35 +01:00
filename = Bottle::Filename.create(f, Utils::Bottles.tag, rebuild)
bottle_path = Pathname.pwd/filename
tar_filename = filename.to_s.sub(/.gz$/, "")
tar_path = Pathname.pwd/tar_filename
prefix = HOMEBREW_PREFIX.to_s
repository = HOMEBREW_REPOSITORY.to_s
cellar = HOMEBREW_CELLAR.to_s
ohai "Bottling #{filename}..."
2013-09-21 21:21:42 +01:00
formula_and_runtime_deps_names = [f.name] + f.runtime_dependencies.map(&:name)
keg = Keg.new(f.prefix)
2020-11-23 18:15:48 +01:00
relocatable = T.let(false, T::Boolean)
skip_relocation = T.let(false, T::Boolean)
keg.lock do
original_tab = nil
changed_files = nil
begin
keg.delete_pyc_files!
changed_files = keg.replace_locations_with_placeholders unless args.skip_relocation?
Formula.clear_cache
2019-11-05 20:33:32 +00:00
Keg.clear_cache
Tab.clear_cache
tab = Tab.for_keg(keg)
original_tab = tab.dup
tab.poured_from_bottle = false
tab.HEAD = nil
tab.time = nil
tab.changed_files = changed_files
tab.write
keg.find do |file|
if file.symlink?
File.lutime(tab.source_modified_time, tab.source_modified_time, file)
else
file.utime(tab.source_modified_time, tab.source_modified_time)
end
end
cd cellar do
sudo_purge
safe_system "tar", "cf", tar_path, "#{f.name}/#{f.pkg_version}"
sudo_purge
tar_path.utime(tab.source_modified_time, tab.source_modified_time)
relocatable_tar_path = "#{f}-bottle.tar"
mv tar_path, relocatable_tar_path
# Use gzip, faster to compress than bzip2, faster to uncompress than bzip2
# or an uncompressed tarball (and more bandwidth friendly).
safe_system "gzip", "-f", relocatable_tar_path
sudo_purge
mv "#{relocatable_tar_path}.gz", bottle_path
end
ohai "Detecting if #{filename} is relocatable..." if bottle_path.size > 1 * 1024 * 1024
2020-03-13 21:15:06 +00:00
prefix_check = if Homebrew.default_prefix?(prefix)
File.join(prefix, "opt")
else
2020-03-13 21:15:06 +00:00
prefix
end
# Ignore matches to source code, which is not required at run time.
# These matches may be caused by debugging symbols.
ignores = [%r{/include/|\.(c|cc|cpp|h|hpp)$}]
any_go_deps = f.deps.any? do |dep|
dep.name =~ Version.formula_optionally_versioned_regex(:go)
end
if any_go_deps
go_regex =
Version.formula_optionally_versioned_regex(:go, full: false)
2020-06-02 09:49:23 +01:00
ignores << %r{#{Regexp.escape(HOMEBREW_CELLAR)}/#{go_regex}/[\d.]+/libexec}
end
relocatable = true
if args.skip_relocation?
skip_relocation = true
else
relocatable = false if keg_contain?(prefix_check, keg, ignores, formula_and_runtime_deps_names, args: args)
relocatable = false if keg_contain?(repository, keg, ignores, args: args)
relocatable = false if keg_contain?(cellar, keg, ignores, formula_and_runtime_deps_names, args: args)
if prefix != prefix_check
2020-08-01 14:56:11 -04:00
relocatable = false if keg_contain_absolute_symlink_starting_with?(prefix, keg, args: args)
relocatable = false if keg_contain?("#{prefix}/etc", keg, ignores, args: args)
relocatable = false if keg_contain?("#{prefix}/var", keg, ignores, args: args)
relocatable = false if keg_contain?("#{prefix}/share/vim", keg, ignores, args: args)
end
skip_relocation = relocatable && !keg.require_relocation?
end
puts if !relocatable && args.verbose?
rescue Interrupt
ignore_interrupts { bottle_path.unlink if bottle_path.exist? }
raise
ensure
ignore_interrupts do
2017-09-24 19:24:46 +01:00
original_tab&.write
keg.replace_placeholders_with_locations changed_files unless args.skip_relocation?
end
end
end
root_url = args.root_url
bottle = BottleSpecification.new
bottle.tap = tap
bottle.root_url(root_url) if root_url
if relocatable
if skip_relocation
bottle.cellar :any_skip_relocation
else
bottle.cellar :any
end
else
bottle.cellar cellar
bottle.prefix prefix
end
2016-08-18 17:32:35 +01:00
bottle.rebuild rebuild
sha256 = bottle_path.sha256
bottle.sha256 sha256 => Utils::Bottles.tag
old_spec = f.bottle_specification
if args.keep_old? && !old_spec.checksums.empty?
2017-05-29 18:24:52 +01:00
mismatches = [:root_url, :prefix, :cellar, :rebuild].reject do |key|
old_spec.send(key) == bottle.send(key)
end
2019-10-15 20:13:04 +02:00
if (old_spec.cellar == :any && bottle.cellar == :any_skip_relocation) ||
(old_spec.cellar == cellar &&
[:any, :any_skip_relocation].include?(bottle.cellar))
mismatches.delete(:cellar)
bottle.cellar old_spec.cellar
end
unless mismatches.empty?
bottle_path.unlink if bottle_path.exist?
mismatches.map! do |key|
old_value = old_spec.send(key).inspect
value = bottle.send(key).inspect
"#{key}: old: #{old_value}, new: #{value}"
end
odie <<~EOS
--keep-old was passed but there are changes in:
#{mismatches.join("\n")}
EOS
end
end
output = bottle_output bottle
puts "./#{filename}"
puts output
return unless args.json?
2018-09-17 02:45:00 +02:00
2016-09-22 20:12:28 +02:00
json = {
f.full_name => {
"formula" => {
"pkg_version" => f.pkg_version.to_s,
2018-11-02 17:18:07 +00:00
"path" => f.path.to_s.delete_prefix("#{HOMEBREW_REPOSITORY}/"),
2016-09-22 20:12:28 +02:00
},
2018-11-02 17:18:07 +00:00
"bottle" => {
2016-09-22 20:12:28 +02:00
"root_url" => bottle.root_url,
2018-11-02 17:18:07 +00:00
"prefix" => bottle.prefix,
"cellar" => bottle.cellar.to_s,
"rebuild" => bottle.rebuild,
"tags" => {
Utils::Bottles.tag.to_s => {
2018-11-02 17:18:07 +00:00
"filename" => filename.bintray,
"local_filename" => filename.to_s,
2018-11-02 17:18:07 +00:00
"sha256" => sha256,
2016-09-11 17:41:51 +01:00
},
},
},
2016-09-22 20:12:28 +02:00
"bintray" => {
2018-11-02 17:18:07 +00:00
"package" => Utils::Bottles::Bintray.package(f.name),
2016-09-22 20:12:28 +02:00
"repository" => Utils::Bottles::Bintray.repository(tap),
},
},
}
2018-08-06 15:02:52 +02:00
File.open(filename.json, "w") do |file|
file.write JSON.generate json
end
end
def parse_json_files(filenames)
filenames.map do |filename|
JSON.parse(IO.read(filename))
end
end
def merge_json_files(json_files)
json_files.reduce({}) do |hash, json_file|
hash.deep_merge(json_file) do |key, first, second|
if key == "cellar"
# Prioritize HOMEBREW_CELLAR over :any over :any_skip_relocation
cellars = [first, second]
2020-11-13 17:21:51 +01:00
next HOMEBREW_CELLAR if cellars.include?(HOMEBREW_CELLAR)
next first if first.start_with?("/")
next second if second.start_with?("/")
next "any" if cellars.include?("any")
next "any_skip_relocation" if cellars.include?("any_skip_relocation")
end
2020-11-13 17:21:51 +01:00
second
end
end
end
def merge(args:)
bottles_hash = merge_json_files(parse_json_files(args.named))
2020-09-11 10:29:21 +01:00
any_cellars = ["any", "any_skip_relocation"]
bottles_hash.each do |formula_name, bottle_hash|
ohai formula_name
bottle = BottleSpecification.new
bottle.root_url bottle_hash["bottle"]["root_url"]
cellar = bottle_hash["bottle"]["cellar"]
2020-09-11 10:29:21 +01:00
cellar = cellar.to_sym if any_cellars.include?(cellar)
bottle.cellar cellar
bottle.prefix bottle_hash["bottle"]["prefix"]
2016-08-18 17:32:35 +01:00
bottle.rebuild bottle_hash["bottle"]["rebuild"]
bottle_hash["bottle"]["tags"].each do |tag, tag_hash|
bottle.sha256 tag_hash["sha256"] => tag.to_sym
end
output = bottle_output bottle
if args.write?
2016-09-11 17:41:51 +01:00
path = Pathname.new((HOMEBREW_REPOSITORY/bottle_hash["formula"]["path"]).to_s)
2020-11-23 18:15:48 +01:00
update_or_add = T.let(nil, T.nilable(String))
2013-12-27 16:43:34 -06:00
Utils::Inreplace.inreplace(path) do |s|
if s.inreplace_string.include? "bottle do"
update_or_add = "update"
if args.keep_old?
mismatches = []
2020-09-11 10:29:21 +01:00
valid_keys = %w[root_url prefix cellar rebuild sha1 sha256]
2020-07-27 17:23:08 +02:00
bottle_block_contents = s.inreplace_string[/ bottle do(.+?)end\n/m, 1]
bottle_block_contents.lines.each do |line|
line = line.strip
next if line.empty?
2018-09-17 02:45:00 +02:00
key, old_value_original, _, tag = line.split " ", 4
2020-09-11 10:29:21 +01:00
next unless valid_keys.include?(key)
2016-05-28 16:46:34 +01:00
old_value = old_value_original.to_s.delete "'\""
old_value = old_value.to_s.delete ":" if key != "root_url"
tag = tag.to_s.delete ":"
2016-09-11 17:41:51 +01:00
unless tag.empty?
if bottle_hash["bottle"]["tags"][tag].present?
mismatches << "#{key} => #{tag}"
else
bottle.send(key, old_value => tag.to_sym)
end
next
end
value_original = bottle_hash["bottle"][key]
value = value_original.to_s
next if key == "cellar" && old_value == "any" && value == "any_skip_relocation"
2016-09-11 17:41:51 +01:00
next unless old_value.empty? || value != old_value
2018-09-17 02:45:00 +02:00
2016-09-11 17:41:51 +01:00
old_value = old_value_original.inspect
value = value_original.inspect
mismatches << "#{key}: old: #{old_value}, new: #{value}"
end
unless mismatches.empty?
odie <<~EOS
--keep-old was passed but there are changes in:
#{mismatches.join("\n")}
EOS
end
output = bottle_output bottle
end
puts output
2014-01-31 19:07:49 +01:00
string = s.sub!(/ bottle do.+?end\n/m, output)
odie "Bottle block update failed!" unless string
else
odie "--keep-old was passed but there was no existing bottle block!" if args.keep_old?
puts output
update_or_add = "add"
pattern = /(
(\ {2}\#[^\n]*\n)* # comments
\ {2}( # two spaces at the beginning
(url|head)\ ['"][\S\ ]+['"] # url or head with a string
(
,[\S\ ]*$ # url may have options
(\n^\ {3}[\S\ ]+$)* # options can be in multiple lines
)?|
(homepage|desc|sha256|version|mirror|license)\ ['"][\S\ ]+['"]| # specs with a string
license\ (
[^\[]+?\[[^\]]+?\]| # license may contain a list
[^{]+?{[^}]+?}| # license may contain a hash
:\S+ # license as a symbol
)|
(revision|version_scheme)\ \d+| # revision with a number
(stable|livecheck)\ do(\n+^\ {4}[\S\ ]+$)*\n+^\ {2}end # components with blocks
)\n+ # multiple empty lines
)+
/mx
2020-08-19 17:12:32 +01:00
string = s.sub!(pattern, "\\0#{output}\n")
odie "Bottle block addition failed!" unless string
end
end
unless args.no_commit?
2020-08-23 06:32:26 +02:00
Utils::Git.set_name_email!
Utils::Git.setup_gpg!
short_name = formula_name.split("/", -1).last
pkg_version = bottle_hash["formula"]["pkg_version"]
path.parent.cd do
safe_system "git", "commit", "--no-edit", "--verbose",
2019-04-30 08:44:35 +01:00
"--message=#{short_name}: #{update_or_add} #{pkg_version} bottle.",
"--", path
end
end
else
puts output
end
end
end
end