Implement cask renames.

This commit is contained in:
Markus Reiter 2023-04-08 14:10:58 +02:00
parent 8ea287cc07
commit a3231a03fa
No known key found for this signature in database
GPG Key ID: 245293B51702655B
30 changed files with 469 additions and 256 deletions

View File

@ -46,8 +46,15 @@ module Homebrew
json_casks, updated = Homebrew::API.fetch_json_api_file "cask.jws.json",
target: HOMEBREW_CACHE_API/"cask.jws.json"
cache["renames"] = {}
cache["casks"] = json_casks.to_h do |json_cask|
[json_cask["token"], json_cask.except("token")]
token = json_cask.delete("token")
json_cask.fetch("old_tokens", []).each do |old_token|
cache["renames"][old_token] = token
end
[token, json_cask]
end
updated
@ -61,7 +68,17 @@ module Homebrew
write_names(regenerate: json_updated)
end
cache["casks"]
cache.fetch("casks")
end
sig { returns(T::Hash[String, String]) }
def all_renames
unless cache.key?("renames")
json_updated = download_and_cache_data!
write_names(regenerate: json_updated)
end
cache.fetch("renames")
end
sig { params(regenerate: T::Boolean).void }

View File

@ -80,7 +80,7 @@ module Homebrew
cache["aliases"]
end
sig { returns(Hash) }
sig { returns(T::Hash[String, String]) }
def all_renames
unless cache.key?("renames")
json_updated = download_and_cache_data!

View File

@ -16,6 +16,7 @@ require "cask/dsl"
require "cask/installer"
require "cask/macos"
require "cask/metadata"
require "cask/migrator"
require "cask/pkg"
require "cask/quarantine"
require "cask/staged"

View File

@ -78,6 +78,17 @@ module Cask
end
end
# An old name for the cask.
sig { returns(T::Array[String]) }
def old_tokens
@old_tokens ||= if tap
tap.cask_renames
.flat_map { |old_token, new_token| (new_token == token) ? old_token : [] }
else
[]
end
end
def config=(config)
@config = config
@ -96,22 +107,18 @@ module Cask
define_method(method_name) { |&block| @dsl.send(method_name, &block) }
end
sig { returns(T::Array[[String, String]]) }
def timestamped_versions
relative_paths = Pathname.glob(metadata_timestamped_path(version: "*", timestamp: "*"))
sig { params(caskroom_path: Pathname).returns(T::Array[[String, String]]) }
def timestamped_versions(caskroom_path: self.caskroom_path)
relative_paths = Pathname.glob(metadata_timestamped_path(
version: "*", timestamp: "*",
caskroom_path: caskroom_path
))
.map { |p| p.relative_path_from(p.parent.parent) }
# Sorbet is unaware that Pathname is sortable: https://github.com/sorbet/sorbet/issues/6844
T.unsafe(relative_paths).sort_by(&:basename) # sort by timestamp
.map { |p| p.split.map(&:to_s) }
end
def versions
timestamped_versions.map(&:first)
.reverse
.uniq
.reverse
end
def full_name
return token if tap.nil?
return token if tap.user == "Homebrew"
@ -119,8 +126,9 @@ module Cask
"#{tap.name}/#{token}"
end
sig { returns(T::Boolean) }
def installed?
!versions.empty?
installed_caskfile&.exist? || false
end
# The caskfile is needed during installation when there are
@ -131,18 +139,41 @@ module Cask
sig { returns(T.nilable(Time)) }
def install_time
_, time = timestamped_versions.last
return unless time
Time.strptime(time, Metadata::TIMESTAMP_FORMAT)
# <caskroom_path>/.metadata/<version>/<timestamp>/Casks/<token>.{rb,json} -> <timestamp>
time = installed_caskfile&.dirname&.dirname&.basename&.to_s
Time.strptime(time, Metadata::TIMESTAMP_FORMAT) if time
end
sig { returns(T.nilable(Pathname)) }
def installed_caskfile
installed_version = timestamped_versions.last
caskfile_dir = metadata_main_container_path.join(*installed_version, "Casks")
return caskfile_dir.join("#{token}.json") if caskfile_dir.join("#{token}.json").exist?
installed_caskroom_path = caskroom_path
installed_token = token
caskfile_dir.join("#{token}.rb")
# Check if the cask is installed with an old name.
old_tokens.each do |old_token|
old_caskroom_path = Caskroom.path/old_token
next if !old_caskroom_path.directory? || old_caskroom_path.symlink?
installed_caskroom_path = old_caskroom_path
installed_token = old_token
break
end
installed_version = timestamped_versions(caskroom_path: installed_caskroom_path).last
return unless installed_version
caskfile_dir = metadata_main_container_path(caskroom_path: installed_caskroom_path)
.join(*installed_version, "Casks")
["json", "rb"]
.map { |ext| caskfile_dir.join("#{installed_token}.#{ext}") }
.find(&:exist?)
end
sig { returns(T.nilable(String)) }
def installed_version
# <caskroom_path>/.metadata/<version>/<timestamp>/Casks/<token>.{rb,json} -> <version>
installed_caskfile&.dirname&.dirname&.dirname&.basename&.to_s
end
def config_path
@ -173,6 +204,7 @@ module Cask
current_download_sha.blank? || current_download_sha != new_download_sha
end
sig { returns(Pathname) }
def caskroom_path
@caskroom_path ||= Caskroom.path.join(token)
end
@ -182,26 +214,23 @@ module Cask
greedy_auto_updates: greedy_auto_updates).empty?
end
# TODO: Rename to `outdated_version` and only return one version.
def outdated_versions(greedy: false, greedy_latest: false, greedy_auto_updates: false)
# special case: tap version is not available
return [] if version.nil?
if version.latest?
return versions if (greedy || greedy_latest) && outdated_download_sha?
return [installed_version] if (greedy || greedy_latest) && outdated_download_sha?
return []
elsif auto_updates && !greedy && !greedy_auto_updates
return []
end
installed = versions
current = installed.last
# not outdated unless there is a different version on tap
return [] if current == version
return [] if installed_version == version
# collect all installed versions that are different than tap version and return them
installed.reject { |v| v == version }
[installed_version]
end
def outdated_info(greedy, verbose, json, greedy_latest, greedy_auto_updates)
@ -279,6 +308,7 @@ module Cask
{
"token" => token,
"full_token" => full_name,
"old_tokens" => old_tokens,
"tap" => tap&.name,
"name" => name,
"desc" => desc,
@ -287,7 +317,7 @@ module Cask
"url_specs" => url_specs,
"appcast" => appcast,
"version" => version,
"installed" => versions.last,
"installed" => installed_version,
"outdated" => outdated?,
"sha256" => sha256,
"artifacts" => artifacts_list,
@ -349,7 +379,7 @@ module Cask
def api_to_local_hash(hash)
hash["token"] = token
hash["installed"] = versions.last
hash["installed"] = installed_version
hash["outdated"] = outdated?
hash
end

View File

@ -401,11 +401,11 @@ module Cask
self.for(ref, need_path: true).path
end
def self.load(ref, config: nil)
self.for(ref).load(config: config)
def self.load(ref, config: nil, warn: true)
self.for(ref, warn: warn).load(config: config)
end
def self.for(ref, need_path: false)
def self.for(ref, need_path: false, warn: true)
[
FromInstanceLoader,
FromContentLoader,
@ -422,7 +422,7 @@ module Cask
end
end
case (possible_tap_casks = tap_paths(ref)).count
case (possible_tap_casks = tap_paths(ref, warn: warn)).count
when 1
return FromTapPathLoader.new(possible_tap_casks.first)
when 2..Float::INFINITY
@ -441,9 +441,13 @@ module Cask
Tap.default_cask_tap.cask_dir/"#{token.to_s.downcase}.rb"
end
def self.tap_paths(token)
def self.tap_paths(token, warn: true)
token = token.to_s.downcase
Tap.map do |tap|
find_cask_in_tap(token.to_s.downcase, tap)
new_token = tap.cask_renames[token]
opoo "Cask #{token} was renamed to #{new_token}." if new_token && warn
find_cask_in_tap(new_token || token, tap)
end.select(&:exist?)
end

View File

@ -13,11 +13,18 @@ module Cask
@path ||= HOMEBREW_PREFIX/"Caskroom"
end
# Return all paths for installed casks.
sig { returns(T::Array[Pathname]) }
def self.paths
return [] unless path.exist?
path.children.select { |p| p.directory? && !p.symlink? }
end
private_class_method :paths
sig { returns(T::Boolean) }
def self.any_casks_installed?
return false unless path.exist?
path.children.select(&:directory?).any?
paths.any?
end
sig { void }
@ -39,9 +46,7 @@ module Cask
sig { params(config: T.nilable(Config)).returns(T::Array[Cask]) }
def self.casks(config: nil)
return [] unless path.exist?
path.children.select(&:directory?).sort.map do |path|
paths.sort.map do |path|
token = path.basename.to_s
begin

View File

@ -39,17 +39,14 @@ module Cask
def self.installation_info(cask)
return "Not installed\n" unless cask.installed?
install_info = +""
cask.versions.each do |version|
versioned_staged_path = cask.caskroom_path.join(version)
versioned_staged_path = cask.caskroom_path.join(cask.installed_version)
path_details = if versioned_staged_path.exist?
versioned_staged_path.abv
else
Formatter.error("does not exist")
end
install_info << "#{versioned_staged_path} (#{path_details})\n"
end
install_info.freeze
"#{versioned_staged_path} (#{path_details})\n"
end
def self.name_info(cask)

View File

@ -7,6 +7,7 @@ require "utils/topological_hash"
require "cask/config"
require "cask/download"
require "cask/migrator"
require "cask/quarantine"
require "cgi"
@ -87,6 +88,8 @@ module Cask
start_time = Time.now
odebug "Cask::Installer#install"
Migrator.migrate_if_needed(@cask)
old_config = @cask.config
if @cask.installed? && !force? && !reinstall? && !upgrade?
return if quiet?
@ -227,8 +230,9 @@ on_request: true)
next if artifact.is_a?(Artifact::Binary) && !binaries?
artifact.install_phase(command: @command, verbose: verbose?, adopt: adopt?, force: force?,
predecessor: predecessor)
artifact.install_phase(
command: @command, verbose: verbose?, adopt: adopt?, force: force?, predecessor: predecessor,
)
already_installed_artifacts.unshift(artifact)
end
@ -382,7 +386,6 @@ on_request: true)
end
def save_config_file
metadata_subdir
@cask.config_path.atomic_write(@cask.config.to_json)
end
@ -408,7 +411,8 @@ on_request: true)
end
def remove_download_sha
FileUtils.rm_f @cask.download_sha_path if @cask.download_sha_path.exist?
FileUtils.rm_f @cask.download_sha_path
@cask.download_sha_path.parent.rmdir_if_possible
end
def start_upgrade(successor:)
@ -424,8 +428,8 @@ on_request: true)
def restore_backup
return if !backup_path.directory? || !backup_metadata_path.directory?
Pathname.new(@cask.staged_path).rmtree if @cask.staged_path.exist?
Pathname.new(@cask.metadata_versioned_path).rmtree if @cask.metadata_versioned_path.exist?
@cask.staged_path.rmtree if @cask.staged_path.exist?
@cask.metadata_versioned_path.rmtree if @cask.metadata_versioned_path.exist?
backup_path.rename @cask.staged_path
backup_metadata_path.rename @cask.metadata_versioned_path
@ -539,6 +543,12 @@ on_request: true)
# toplevel staged distribution
@cask.caskroom_path.rmdir_if_possible unless upgrade?
# Remove symlinks for renamed casks if they are now broken.
@cask.old_tokens.each do |old_token|
old_caskroom_path = Caskroom.path/old_token
FileUtils.rm old_caskroom_path if old_caskroom_path.symlink? && !old_caskroom_path.exist?
end
end
def purge_caskroom_path
@ -550,9 +560,11 @@ on_request: true)
# load the same cask file that was used for installation, if possible
def load_installed_caskfile!
Migrator.migrate_if_needed(@cask)
installed_caskfile = @cask.installed_caskfile
if installed_caskfile.exist?
if installed_caskfile&.exist?
begin
@cask = CaskLoader.load(installed_caskfile)
return

View File

@ -43,7 +43,7 @@ module Cask
end
def self.format_versioned(cask)
cask.to_s.concat(cask.versions.map(&:to_s).join(" ").prepend(" "))
"#{cask}#{cask.installed_version&.prepend(" ")}"
end
end
end

View File

@ -9,26 +9,27 @@ module Cask
METADATA_SUBDIR = ".metadata"
TIMESTAMP_FORMAT = "%Y%m%d%H%M%S.%L"
def metadata_main_container_path
@metadata_main_container_path ||= caskroom_path.join(METADATA_SUBDIR)
def metadata_main_container_path(caskroom_path: self.caskroom_path)
caskroom_path.join(METADATA_SUBDIR)
end
def metadata_versioned_path(version: self.version)
def metadata_versioned_path(version: self.version, caskroom_path: self.caskroom_path)
cask_version = (version || :unknown).to_s
raise CaskError, "Cannot create metadata path with empty version." if cask_version.empty?
metadata_main_container_path.join(cask_version)
metadata_main_container_path(caskroom_path: caskroom_path).join(cask_version)
end
def metadata_timestamped_path(version: self.version, timestamp: :latest, create: false)
def metadata_timestamped_path(version: self.version, timestamp: :latest, create: false,
caskroom_path: self.caskroom_path)
raise CaskError, "Cannot create metadata path when timestamp is :latest." if create && timestamp == :latest
path = if timestamp == :latest
Pathname.glob(metadata_versioned_path(version: version).join("*")).max
Pathname.glob(metadata_versioned_path(version: version, caskroom_path: caskroom_path).join("*")).max
else
timestamp = new_timestamp if timestamp == :now
metadata_versioned_path(version: version).join(timestamp)
metadata_versioned_path(version: version, caskroom_path: caskroom_path).join(timestamp)
end
if create && !path.directory?
@ -39,11 +40,13 @@ module Cask
path
end
def metadata_subdir(leaf, version: self.version, timestamp: :latest, create: false)
def metadata_subdir(leaf, version: self.version, timestamp: :latest, create: false,
caskroom_path: self.caskroom_path)
raise CaskError, "Cannot create metadata subdir when timestamp is :latest." if create && timestamp == :latest
raise CaskError, "Cannot create metadata subdir for empty leaf." if !leaf.respond_to?(:empty?) || leaf.empty?
parent = metadata_timestamped_path(version: version, timestamp: timestamp, create: create)
parent = metadata_timestamped_path(version: version, timestamp: timestamp, create: create,
caskroom_path: caskroom_path)
return if parent.nil?

View File

@ -0,0 +1,86 @@
# typed: true
# frozen_string_literal: true
require "cask/cask_loader"
require "utils/inreplace"
module Cask
class Migrator
extend ::Utils::Inreplace
attr_reader :old_cask, :new_cask
sig { params(old_cask: Cask, new_cask: Cask).void }
def initialize(old_cask, new_cask)
raise CaskNotInstalledError, new_cask unless new_cask.installed?
@old_cask = old_cask
@new_cask = new_cask
end
sig { params(new_cask: Cask, dry_run: T::Boolean).void }
def self.migrate_if_needed(new_cask, dry_run: false)
old_tokens = new_cask.old_tokens
return if old_tokens.empty?
return unless (installed_caskfile = new_cask.installed_caskfile)
installed_token = installed_caskfile.relative_path_from(Caskroom.path).basename.to_s
return if new_cask.token == installed_token
old_cask = CaskLoader.load(installed_caskfile)
migrator = new(old_cask, new_cask)
migrator.migrate(dry_run: dry_run)
end
sig { params(dry_run: T::Boolean).void }
def migrate(dry_run: false)
old_token = old_cask.token
new_token = new_cask.token
old_caskroom_path = old_cask.caskroom_path
new_caskroom_path = new_cask.caskroom_path
old_installed_caskfile = old_cask.installed_caskfile.relative_path_from(old_caskroom_path)
new_installed_caskfile = old_installed_caskfile.dirname/old_installed_caskfile.basename.sub(
old_token,
new_token,
)
if dry_run
oh1 "Would migrate cask #{Formatter.identifier(old_token)} to #{Formatter.identifier(new_token)}"
puts "cp -r #{old_caskroom_path} #{new_caskroom_path}"
puts "mv #{new_caskroom_path}/#{old_installed_caskfile} #{new_caskroom_path}/#{new_installed_caskfile}"
puts "rm -r #{old_caskroom_path}"
puts "ln -s #{new_caskroom_path.basename} #{old_caskroom_path}"
else
oh1 "Migrating cask #{Formatter.identifier(old_token)} to #{Formatter.identifier(new_token)}"
begin
FileUtils.cp_r old_caskroom_path, new_caskroom_path
FileUtils.mv new_caskroom_path/old_installed_caskfile, new_caskroom_path/new_installed_caskfile
self.class.replace_caskfile_token(new_caskroom_path/new_installed_caskfile, old_token, new_token)
rescue => e
FileUtils.rm_rf new_caskroom_path
raise e
end
FileUtils.rm_r old_caskroom_path
FileUtils.ln_s new_caskroom_path.basename, old_caskroom_path
end
end
sig { params(path: Pathname, old_token: String, new_token: String).void }
def self.replace_caskfile_token(path, old_token, new_token)
case path.extname
when ".rb"
inreplace path, /\A\s*cask\s+"#{Regexp.escape(old_token)}"/, "cask #{new_token.inspect}"
when ".json"
json = JSON.parse(path.read)
json["token"] = new_token
path.atomic_write json.to_json
end
end
end
end

View File

@ -13,13 +13,6 @@ module Cask
raise CaskNotInstalledError, cask if !cask.installed? && !force
Installer.new(cask, binaries: binaries, force: force, verbose: verbose).uninstall
next if (versions = cask.versions).empty?
puts <<~EOS
#{cask} #{versions.to_sentence} #{(versions.count == 1) ? "is" : "are"} still installed.
Remove #{(versions.count == 1) ? "it" : "them all"} with `brew uninstall --cask --force #{cask}`.
EOS
end
end
end

View File

@ -95,8 +95,7 @@ module Cask
caught_exceptions = []
upgradable_casks = outdated_casks.map do |c|
if !c.installed_caskfile.exist? && c.tap.to_s == "homebrew/cask" &&
Homebrew::API::Cask.all_casks.key?(c.token)
if !c.installed? && c.tap.to_s == "homebrew/cask" && Homebrew::API::Cask.all_casks.key?(c.token)
odie <<~EOS
The cask '#{c.token}' was affected by a bug and cannot be upgraded as-is. To fix this, run:
brew reinstall --cask --force #{c.token}
@ -192,7 +191,7 @@ module Cask
new_cask_installer.install_artifacts(predecessor: old_cask)
new_artifacts_installed = true
# If successful, wipe the old cask from staging
# If successful, wipe the old cask from staging.
old_cask_installer.finalize_upgrade
rescue => e
new_cask_installer.uninstall_artifacts(successor: old_cask) if new_artifacts_installed

View File

@ -155,7 +155,7 @@ module Homebrew
return false if cask.blank?
return true unless basename.to_s.match?(/\A#{Regexp.escape(name)}--#{Regexp.escape(cask.version)}\b/)
return true if scrub && cask.versions.exclude?(cask.version)
return true if scrub && cask.installed_version != cask.version
if cask.version.latest?
cleanup_threshold = (DateTime.now - CLEANUP_DEFAULT_DAYS).to_time

View File

@ -47,12 +47,14 @@ module Homebrew
ignore_unavailable: T.nilable(T::Boolean),
method: T.nilable(Symbol),
uniq: T::Boolean,
warn: T::Boolean,
).returns(T::Array[T.any(Formula, Keg, Cask::Cask)])
}
def to_formulae_and_casks(only: parent&.only_formula_or_cask, ignore_unavailable: nil, method: nil, uniq: true)
def to_formulae_and_casks(only: parent&.only_formula_or_cask, ignore_unavailable: nil, method: nil, uniq: true,
warn: true)
@to_formulae_and_casks ||= {}
@to_formulae_and_casks[only] ||= downcased_unique_named.flat_map do |name|
load_formula_or_cask(name, only: only, method: method)
load_formula_or_cask(name, only: only, method: method, warn: warn)
rescue FormulaUnreadableError, FormulaClassUnavailableError,
TapFormulaUnreadableError, TapFormulaClassUnavailableError,
Cask::CaskUnreadableError
@ -86,14 +88,14 @@ module Homebrew
end.uniq.freeze
end
def load_formula_or_cask(name, only: nil, method: nil)
def load_formula_or_cask(name, only: nil, method: nil, warn: true)
unreadable_error = nil
if only != :cask
begin
formula = case method
when nil, :factory
Formulary.factory(name, *spec, force_bottle: @force_bottle, flags: @flags)
Formulary.factory(name, *spec, force_bottle: @force_bottle, flags: @flags, warn: warn)
when :resolve
resolve_formula(name)
when :latest_kegs
@ -124,7 +126,7 @@ module Homebrew
begin
config = Cask::Config.from_args(@parent) if @cask_options
cask = Cask::CaskLoader.load(name, config: config)
cask = Cask::CaskLoader.load(name, config: config, warn: warn)
if unreadable_error.present?
onoe <<~EOS
@ -145,7 +147,7 @@ module Homebrew
# If we're trying to get a keg-like Cask, do our best to handle it
# not being readable and return something that can be used.
if want_keg_like_cask
cask_version = Cask::Cask.new(name, config: config).versions.first
cask_version = Cask::Cask.new(name, config: config).installed_version
cask = Cask::Cask.new(name, config: config) do
version cask_version if cask_version
end

View File

@ -3,12 +3,11 @@
require "migrator"
require "cli/parser"
require "cask/migrator"
module Homebrew
module_function
sig { returns(CLI::Parser) }
def migrate_args
def self.migrate_args
Homebrew::CLI::Parser.new do
description <<~EOS
Migrate renamed packages to new names, where <formula> are old names of
@ -19,17 +18,27 @@ module Homebrew
"the same taps and migrate them anyway."
switch "-n", "--dry-run",
description: "Show what would be migrated, but do not actually migrate anything."
switch "--formula", "--formulae",
description: "Only migrate formulae."
switch "--cask", "--casks",
description: "Only migrate casks."
named_args :installed_formula, min: 1
conflicts "--formula", "--cask"
named_args [:installed_formula, :installed_cask], min: 1
end
end
def migrate
def self.migrate
args = migrate_args.parse
args.named.to_kegs.each do |keg|
f = Formulary.from_keg(keg)
Migrator.migrate_if_needed(f, force: args.force?, dry_run: args.dry_run?)
args.named.to_formulae_and_casks(warn: false).each do |formula_or_cask|
case formula_or_cask
when Formula
Migrator.migrate_if_needed(formula_or_cask, force: args.force?, dry_run: args.dry_run?)
when Cask::Cask
Cask::Migrator.migrate_if_needed(formula_or_cask, dry_run: args.dry_run?)
end
end
end
end

View File

@ -3,6 +3,7 @@
require "migrator"
require "formulary"
require "cask/cask_loader"
require "descriptions"
require "cleanup"
require "description_cache_store"
@ -246,6 +247,7 @@ module Homebrew
hub.dump(auto_update: args.auto_update?) unless args.quiet?
hub.reporters.each(&:migrate_tap_migration)
hub.reporters.each(&:migrate_cask_rename)
hub.reporters.each { |r| r.migrate_formula_rename(force: args.force?, verbose: args.verbose?) }
CacheStoreDatabase.use(:descriptions) do |db|
@ -390,6 +392,14 @@ class Reporter
when "M"
# Report updated casks
@report[:MC] << tap.formula_file_to_name(src)
when /^R\d{0,3}/
src_full_name = tap.formula_file_to_name(src)
dst_full_name = tap.formula_file_to_name(dst)
# Don't report formulae that are moved within a tap but not renamed
next if src_full_name == dst_full_name
@report[:DC] << src_full_name
@report[:AC] << dst_full_name
end
end
@ -416,6 +426,41 @@ class Reporter
end
end
renamed_casks = Set.new
@report[:DC].each do |old_full_name|
old_name = old_full_name.split("/").last
new_name = tap.cask_renames[old_name]
next unless new_name
new_full_name = if tap.name == "homebrew/cask"
new_name
else
"#{tap}/#{new_name}"
end
renamed_casks << [old_full_name, new_full_name] if @report[:AC].include?(new_full_name)
end
@report[:AC].each do |new_full_name|
new_name = new_full_name.split("/").last
old_name = tap.cask_renames.key(new_name)
next unless old_name
old_full_name = if tap.name == "homebrew/cask"
old_name
else
"#{tap}/#{old_name}"
end
renamed_casks << [old_full_name, new_full_name]
end
if renamed_casks.any?
@report[:AC] -= renamed_casks.map(&:last)
@report[:DC] -= renamed_casks.map(&:first)
@report[:RC] = renamed_casks.to_a
end
renamed_formulae = Set.new
@report[:D].each do |old_full_name|
old_name = old_full_name.split("/").last
@ -445,7 +490,7 @@ class Reporter
renamed_formulae << [old_full_name, new_full_name]
end
if renamed_formulae.present?
if renamed_formulae.any?
@report[:A] -= renamed_formulae.map(&:last)
@report[:D] -= renamed_formulae.map(&:first)
@report[:R] = renamed_formulae.to_a
@ -541,6 +586,12 @@ class Reporter
end
end
def migrate_cask_rename
Cask::Caskroom.casks.each do |cask|
Cask::Migrator.migrate_if_needed(cask)
end
end
def migrate_formula_rename(force:, verbose:)
Formula.installed.each do |formula|
next unless Migrator.needs_migration?(formula)
@ -631,6 +682,7 @@ class ReporterHub
dump_new_formula_report
dump_new_cask_report
dump_renamed_formula_report if report_all
dump_renamed_cask_report if report_all
dump_deleted_formula_report(report_all)
dump_deleted_cask_report(report_all)
@ -723,6 +775,16 @@ class ReporterHub
output_dump_formula_or_cask_report "Renamed Formulae", formulae
end
def dump_renamed_cask_report
casks = select_formula_or_cask(:RC).sort.map do |name, new_name|
name = pretty_installed(name) if installed?(name)
new_name = pretty_installed(new_name) if installed?(new_name)
"#{name} -> #{new_name}"
end
output_dump_formula_or_cask_report "Renamed Casks", casks
end
def dump_deleted_formula_report(report_all)
formulae = select_formula_or_cask(:D).sort.map do |name|
if installed?(name)

View File

@ -502,7 +502,8 @@ class Formula
# Old names for the formula.
def oldnames
@oldnames ||= if tap
tap.formula_renames.select { |_, oldname| oldname == name }.keys
tap.formula_renames
.flat_map { |old_name, new_name| (new_name == name) ? old_name : [] }
else
[]
end

View File

@ -523,8 +523,7 @@ module Formulary
# Loads tapped formulae.
class TapLoader < FormulaLoader
def initialize(tapped_name, from: nil)
warn = [:keg, :rack].exclude?(from)
def initialize(tapped_name, from: nil, warn: true)
name, path, tap = formula_name_path(tapped_name, warn: warn)
super name, path, tap: tap
end
@ -555,7 +554,7 @@ module Formulary
new_name = new_tap.core_tap? ? name : new_tapped_name
end
opoo "Use #{new_name} instead of deprecated #{old_name}" if warn && old_name && new_name
opoo "Formula #{old_name} was renamed to #{new_name}." if warn && old_name && new_name
end
[name, path, tap]
@ -649,7 +648,7 @@ module Formulary
# * a formula URL
# * a local bottle reference
def self.factory(
ref, spec = :stable, alias_path: nil, from: nil,
ref, spec = :stable, alias_path: nil, from: nil, warn: true,
force_bottle: false, flags: [], ignore_errors: false
)
raise ArgumentError, "Formulae must have a ref!" unless ref
@ -660,7 +659,7 @@ module Formulary
return cache[:formulary_factory][cache_key]
end
formula = loader_for(ref, from: from).get_formula(spec, alias_path: alias_path,
formula = loader_for(ref, from: from, warn: warn).get_formula(spec, alias_path: alias_path,
force_bottle: force_bottle, flags: flags,
ignore_errors: ignore_errors)
if factory_cached?
@ -683,7 +682,7 @@ module Formulary
if keg
from_keg(keg, spec, alias_path: alias_path, force_bottle: force_bottle, flags: flags)
else
factory(rack.basename.to_s, spec || :stable, alias_path: alias_path, from: :rack,
factory(rack.basename.to_s, spec || :stable, alias_path: alias_path, from: :rack, warn: false,
force_bottle: force_bottle, flags: flags)
end
end
@ -704,15 +703,15 @@ module Formulary
spec ||= tab.spec
f = if tap.nil?
factory(keg.rack.basename.to_s, spec, alias_path: alias_path, from: :keg,
factory(keg.rack.basename.to_s, spec, alias_path: alias_path, from: :keg, warn: false,
force_bottle: force_bottle, flags: flags)
else
begin
factory("#{tap}/#{keg.rack.basename}", spec, alias_path: alias_path, from: :keg,
factory("#{tap}/#{keg.rack.basename}", spec, alias_path: alias_path, from: :keg, warn: false,
force_bottle: force_bottle, flags: flags)
rescue FormulaUnavailableError
# formula may be migrated to different tap. Try to search in core and all taps.
factory(keg.rack.basename.to_s, spec, alias_path: alias_path, from: :keg,
factory(keg.rack.basename.to_s, spec, alias_path: alias_path, from: :keg, warn: false,
force_bottle: force_bottle, flags: flags)
end
end
@ -757,7 +756,7 @@ module Formulary
loader_for(ref).path
end
def self.loader_for(ref, from: nil)
def self.loader_for(ref, from: nil, warn: true)
case ref
when HOMEBREW_BOTTLES_EXTNAME_REGEX
return BottleLoader.new(ref)
@ -770,7 +769,7 @@ module Formulary
return AliasAPILoader.new(name) if Homebrew::API::Formula.all_aliases.key?(name)
end
return TapLoader.new(ref, from: from)
return TapLoader.new(ref, from: from, warn: warn)
end
pathname_ref = Pathname.new(ref)
@ -800,7 +799,9 @@ module Formulary
return FormulaLoader.new(name, path)
end
return TapLoader.new("#{CoreTap.instance}/#{ref}", from: from) if CoreTap.instance.formula_renames.key?(ref)
if CoreTap.instance.formula_renames.key?(ref)
return TapLoader.new("#{CoreTap.instance}/#{ref}", from: from, warn: warn)
end
possible_taps = Tap.select { |tap| tap.formula_renames.key?(ref) }
@ -809,7 +810,7 @@ module Formulary
raise TapFormulaWithOldnameAmbiguityError.new(ref, possible_tap_newname_formulae)
end
return TapLoader.new("#{possible_taps.first}/#{ref}", from: from) unless possible_taps.empty?
return TapLoader.new("#{possible_taps.first}/#{ref}", from: from, warn: warn) unless possible_taps.empty?
possible_keg_formula = Pathname.new("#{HOMEBREW_PREFIX}/opt/#{ref}/.brew/#{ref}.rb")
return FormulaLoader.new(ref, possible_keg_formula) if possible_keg_formula.file?

View File

@ -106,15 +106,14 @@ class Migrator
def self.migrate_if_needed(formula, force:, dry_run: false)
oldnames = Migrator.oldnames_needing_migration(formula)
return if oldnames.empty?
begin
oldnames.each do |oldname|
if dry_run
ohai "Would migrate #{oldnames.to_sentence} to #{formula.name}"
return
oh1 "Would migrate formula #{Formatter.identifier(oldname)} to #{Formatter.identifier(formula.name)}"
next
end
oldnames.each do |oldname|
migrator = Migrator.new(formula, oldname, force: force)
migrator.migrate
end
@ -205,7 +204,7 @@ class Migrator
end
def migrate
oh1 "Processing #{Formatter.identifier(oldname)} formula rename to #{Formatter.identifier(newname)}"
oh1 "Migrating formula #{Formatter.identifier(oldname)} to #{Formatter.identifier(newname)}"
lock
unlink_oldname
unlink_newname if new_cellar.exist?

View File

@ -18,6 +18,7 @@ class Tap
TAP_DIRECTORY = (HOMEBREW_LIBRARY/"Taps").freeze
HOMEBREW_TAP_CASK_RENAMES_FILE = "cask_renames.json"
HOMEBREW_TAP_FORMULA_RENAMES_FILE = "formula_renames.json"
HOMEBREW_TAP_MIGRATIONS_FILE = "tap_migrations.json"
HOMEBREW_TAP_AUDIT_EXCEPTIONS_DIR = "audit_exceptions"
@ -26,6 +27,7 @@ class Tap
HOMEBREW_TAP_JSON_FILES = %W[
#{HOMEBREW_TAP_FORMULA_RENAMES_FILE}
#{HOMEBREW_TAP_CASK_RENAMES_FILE}
#{HOMEBREW_TAP_MIGRATIONS_FILE}
#{HOMEBREW_TAP_AUDIT_EXCEPTIONS_DIR}/*.json
#{HOMEBREW_TAP_STYLE_EXCEPTIONS_DIR}/*.json
@ -687,8 +689,20 @@ class Tap
hash
end
# Hash with tap cask renames.
sig { returns(T::Hash[String, String]) }
def cask_renames
@cask_renames ||= if name == "homebrew/cask" && !Homebrew::EnvConfig.no_install_from_api?
Homebrew::API::Cask.all_renames
elsif (rename_file = path/HOMEBREW_TAP_CASK_RENAMES_FILE).file?
JSON.parse(rename_file.read)
else
{}
end
end
# Hash with tap formula renames.
sig { returns(Hash) }
sig { returns(T::Hash[String, String]) }
def formula_renames
@formula_renames ||= if (rename_file = path/HOMEBREW_TAP_FORMULA_RENAMES_FILE).file?
JSON.parse(rename_file.read)
@ -931,7 +945,7 @@ class CoreTap < Tap
end
# @private
sig { returns(Hash) }
sig { returns(T::Hash[String, String]) }
def formula_renames
@formula_renames ||= if Homebrew::EnvConfig.no_install_from_api?
self.class.ensure_installed!

View File

@ -4,7 +4,7 @@ describe Cask::Cask, :cask do
let(:cask) { described_class.new("versioned-cask") }
context "when multiple versions are installed" do
describe "#versions" do
describe "#installed_version" do
context "when there are duplicate versions" do
it "uses the last unique version" do
allow(cask).to receive(:timestamped_versions).and_return([
@ -13,11 +13,11 @@ describe Cask::Cask, :cask do
["1.2.2", "1001"],
])
# Installed caskfile must exist to count as installed.
allow_any_instance_of(Pathname).to receive(:exist?).and_return(true)
expect(cask).to receive(:timestamped_versions)
expect(cask.versions).to eq([
"1.2.3",
"1.2.2",
])
expect(cask.installed_version).to eq("1.2.2")
end
end
end
@ -104,10 +104,10 @@ describe Cask::Cask, :cask do
let(:cask) { described_class.new("basic-cask") }
shared_examples "versioned casks" do |tap_version, expectations|
expectations.each do |installed_versions, expected_output|
context "when versions #{installed_versions.inspect} are installed and the tap version is #{tap_version}" do
expectations.each do |installed_version, expected_output|
context "when version #{installed_version.inspect} is installed and the tap version is #{tap_version}" do
it {
allow(cask).to receive(:versions).and_return(installed_versions)
allow(cask).to receive(:installed_version).and_return(installed_version)
allow(cask).to receive(:version).and_return(Cask::DSL::Version.new(tap_version))
expect(cask).to receive(:outdated_versions).and_call_original
expect(subject).to eq expected_output
@ -118,16 +118,13 @@ describe Cask::Cask, :cask do
describe "installed version is equal to tap version => not outdated" do
include_examples "versioned casks", "1.2.3",
["1.2.3"] => [],
["1.2.4", "1.2.3"] => []
"1.2.3" => []
end
describe "installed version is different than tap version => outdated" do
include_examples "versioned casks", "1.2.4",
["1.2.3"] => ["1.2.3"],
["1.2.4", "1.2.3"] => ["1.2.3"],
["1.2.2", "1.2.3"] => ["1.2.2", "1.2.3"],
["1.2.2", "1.2.4", "1.2.3"] => ["1.2.2", "1.2.3"]
"1.2.3" => ["1.2.3"],
"1.2.4" => []
end
end
@ -142,7 +139,7 @@ describe Cask::Cask, :cask do
subject { cask.outdated_versions(greedy: greedy) }
it {
allow(cask).to receive(:versions).and_return(installed_version)
allow(cask).to receive(:installed_version).and_return(installed_version)
allow(cask).to receive(:version).and_return(Cask::DSL::Version.new(tap_version))
allow(cask).to receive(:outdated_download_sha?).and_return(outdated_sha)
expect(cask).to receive(:outdated_versions).and_call_original
@ -154,29 +151,29 @@ describe Cask::Cask, :cask do
describe ":latest version installed, :latest version in tap" do
include_examples ":latest cask", false, false, "latest",
["latest"] => []
"latest" => []
include_examples ":latest cask", true, false, "latest",
["latest"] => []
"latest" => []
include_examples ":latest cask", true, true, "latest",
["latest"] => ["latest"]
"latest" => ["latest"]
end
describe "numbered version installed, :latest version in tap" do
include_examples ":latest cask", false, false, "latest",
["1.2.3"] => []
"1.2.3" => []
include_examples ":latest cask", true, false, "latest",
["1.2.3"] => []
"1.2.3" => []
include_examples ":latest cask", true, true, "latest",
["1.2.3"] => ["1.2.3"]
"1.2.3" => ["1.2.3"]
end
describe "latest version installed, numbered version in tap" do
include_examples ":latest cask", false, false, "1.2.3",
["latest"] => ["latest"]
"latest" => ["latest"]
include_examples ":latest cask", true, false, "1.2.3",
["latest"] => ["latest"]
"latest" => ["latest"]
include_examples ":latest cask", true, true, "1.2.3",
["latest"] => ["latest"]
"latest" => ["latest"]
end
end
end

View File

@ -313,7 +313,7 @@ describe Cask::Installer, :cask do
caffeine = Cask::CaskLoader.load(path)
expect(caffeine).to receive(:loaded_from_api?).twice.and_return(true)
expect(caffeine).to receive(:caskfile_only?).twice.and_return(true)
expect(caffeine).to receive(:installed_caskfile).once.and_return(invalid_path)
expect(caffeine).to receive(:installed_caskfile).twice.and_return(invalid_path)
described_class.new(caffeine).install
expect(Cask::CaskLoader.load(path)).to be_installed

View File

@ -112,14 +112,6 @@ describe Cask::Uninstall, :cask do
expect(caskroom_path.join(first_installed_version)).not_to exist
expect(caskroom_path).not_to exist
end
it "displays a message when versions remain installed" do
expect do
expect do
described_class.uninstall_casks(Cask::Cask.new("versioned-cask"))
end.not_to output.to_stderr
end.to output(/#{token} #{first_installed_version} is still installed./).to_stdout
end
end
context "when Casks in Taps have been renamed or removed" do

View File

@ -3,8 +3,12 @@
require "cask/upgrade"
describe Cask::Upgrade, :cask do
let(:version_latest_path_second) { version_latest.config.appdir.join("Caffeine Pro.app") }
let(:version_latest_path_first) { version_latest.config.appdir.join("Caffeine Mini.app") }
let(:version_latest_paths) do
[
version_latest.config.appdir.join("Caffeine Mini.app"),
version_latest.config.appdir.join("Caffeine Pro.app"),
]
end
let(:version_latest) { Cask::CaskLoader.load("version-latest") }
let(:auto_updates_path) { auto_updates.config.appdir.join("MyFancyApp.app") }
let(:auto_updates) { Cask::CaskLoader.load("auto-updates") }
@ -38,81 +42,81 @@ describe Cask::Upgrade, :cask do
it "updates all the installed Casks when no token is provided" do
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.installed_version).to eq "1.2.2"
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(local_transmission.installed_version).to eq "2.60"
expect(renamed_app).to be_installed
expect(renamed_app_old_path).to be_a_directory
expect(renamed_app_new_path).not_to be_a_directory
expect(renamed_app.versions).to include("1.0.0")
expect(renamed_app.installed_version).to eq "1.0.0"
described_class.upgrade_casks(args: args)
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.3")
expect(local_caffeine.installed_version).to eq "1.2.3"
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.61")
expect(local_transmission.installed_version).to eq "2.61"
expect(renamed_app).to be_installed
expect(renamed_app_old_path).not_to be_a_directory
expect(renamed_app_new_path).to be_a_directory
expect(renamed_app.versions).to include("2.0.0")
expect(renamed_app.installed_version).to eq "2.0.0"
end
it "updates only the Casks specified in the command line" do
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.installed_version).to eq "1.2.2"
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(local_transmission.installed_version).to eq "2.60"
expect(renamed_app).to be_installed
expect(renamed_app_old_path).to be_a_directory
expect(renamed_app_new_path).not_to be_a_directory
expect(renamed_app.versions).to include("1.0.0")
expect(renamed_app.installed_version).to eq "1.0.0"
described_class.upgrade_casks(local_caffeine, args: args)
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.3")
expect(local_caffeine.installed_version).to eq "1.2.3"
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(local_transmission.installed_version).to eq "2.60"
expect(renamed_app).to be_installed
expect(renamed_app_old_path).to be_a_directory
expect(renamed_app_new_path).not_to be_a_directory
expect(renamed_app.versions).to include("1.0.0")
expect(renamed_app.installed_version).to eq "1.0.0"
end
it 'updates "auto_updates" and "latest" Casks when their tokens are provided in the command line' do
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.installed_version).to eq "1.2.2"
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57")
expect(auto_updates.installed_version).to eq "2.57"
described_class.upgrade_casks(local_caffeine, auto_updates, args: args)
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.3")
expect(local_caffeine.installed_version).to eq "1.2.3"
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.61")
expect(auto_updates.installed_version).to eq "2.61"
end
end
@ -120,24 +124,24 @@ describe Cask::Upgrade, :cask do
it 'includes the Casks with "auto_updates true" or "version latest"' do
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.installed_version).to eq "1.2.2"
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57")
expect(auto_updates.installed_version).to eq "2.57"
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(local_transmission.installed_version).to eq "2.60"
expect(renamed_app).to be_installed
expect(renamed_app_old_path).to be_a_directory
expect(renamed_app_new_path).not_to be_a_directory
expect(renamed_app.versions).to include("1.0.0")
expect(renamed_app.installed_version).to eq "1.0.0"
expect(version_latest).to be_installed
expect(version_latest_path_first).to be_a_directory
expect(version_latest.versions).to include("latest")
expect(version_latest_paths).to all be_a_directory
expect(version_latest.installed_version).to eq "latest"
# Change download sha so that :latest cask decides to update itself
version_latest.download_sha_path.write("fake download sha")
expect(version_latest.outdated_download_sha?).to be(true)
@ -146,50 +150,49 @@ describe Cask::Upgrade, :cask do
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.3")
expect(local_caffeine.installed_version).to eq "1.2.3"
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.61")
expect(auto_updates.installed_version).to eq "2.61"
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.61")
expect(local_transmission.installed_version).to eq "2.61"
expect(renamed_app).to be_installed
expect(renamed_app_old_path).not_to be_a_directory
expect(renamed_app_new_path).to be_a_directory
expect(renamed_app.versions).to include("2.0.0")
expect(renamed_app.installed_version).to eq "2.0.0"
expect(version_latest).to be_installed
expect(version_latest_path_second).to be_a_directory
expect(version_latest.versions).to include("latest")
expect(version_latest_paths).to all be_a_directory
expect(version_latest.installed_version).to eq "latest"
expect(version_latest.outdated_download_sha?).to be(false)
end
it 'does not include the Casks with "auto_updates true" or "version latest" when the version did not change' do
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57")
expect(auto_updates.installed_version).to eq "2.57"
described_class.upgrade_casks(auto_updates, greedy: true, args: args)
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.61")
expect(auto_updates.installed_version).to eq "2.61"
described_class.upgrade_casks(auto_updates, greedy: true, args: args)
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.61")
expect(auto_updates.installed_version).to eq "2.61"
end
it 'does not include the Casks with "version latest" when the version did not change' do
expect(version_latest).to be_installed
expect(version_latest_path_first).to be_a_directory
expect(version_latest_path_second).to be_a_directory
expect(version_latest.versions).to include("latest")
expect(version_latest_paths).to all be_a_directory
expect(version_latest.installed_version).to eq "latest"
# Change download sha so that :latest cask decides to update itself
version_latest.download_sha_path.write("fake download sha")
expect(version_latest.outdated_download_sha?).to be(true)
@ -197,17 +200,15 @@ describe Cask::Upgrade, :cask do
described_class.upgrade_casks(version_latest, greedy: true, args: args)
expect(version_latest).to be_installed
expect(version_latest_path_first).to be_a_directory
expect(version_latest_path_second).to be_a_directory
expect(version_latest.versions).to include("latest")
expect(version_latest_paths).to all be_a_directory
expect(version_latest.installed_version).to eq "latest"
expect(version_latest.outdated_download_sha?).to be(false)
described_class.upgrade_casks(version_latest, greedy: true, args: args)
expect(version_latest).to be_installed
expect(version_latest_path_first).to be_a_directory
expect(version_latest_path_second).to be_a_directory
expect(version_latest.versions).to include("latest")
expect(version_latest_paths).to all be_a_directory
expect(version_latest.installed_version).to eq "latest"
expect(version_latest.outdated_download_sha?).to be(false)
end
end
@ -236,34 +237,31 @@ describe Cask::Upgrade, :cask do
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.installed_version).to eq "1.2.2"
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(local_transmission.installed_version).to eq "2.60"
expect(renamed_app).to be_installed
expect(renamed_app_old_path).to be_a_directory
expect(renamed_app_new_path).not_to be_a_directory
expect(renamed_app.versions).to include("1.0.0")
expect(renamed_app.installed_version).to eq "1.0.0"
described_class.upgrade_casks(dry_run: true, args: args)
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.versions).not_to include("1.2.3")
expect(local_caffeine.installed_version).to eq "1.2.2"
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(local_transmission.versions).not_to include("2.61")
expect(local_transmission.installed_version).to eq "2.60"
expect(renamed_app).to be_installed
expect(renamed_app_old_path).to be_a_directory
expect(renamed_app_new_path).not_to be_a_directory
expect(renamed_app.versions).to include("1.0.0")
expect(renamed_app.versions).not_to include("2.0.0")
expect(renamed_app.installed_version).to eq "1.0.0"
end
it "would update only the Casks specified in the command line" do
@ -271,23 +269,21 @@ describe Cask::Upgrade, :cask do
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.installed_version).to eq "1.2.2"
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(local_transmission.installed_version).to eq "2.60"
described_class.upgrade_casks(local_caffeine, dry_run: true, args: args)
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.versions).not_to include("1.2.3")
expect(local_caffeine.installed_version).to eq "1.2.2"
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(local_transmission.versions).not_to include("2.61")
expect(local_transmission.installed_version).to eq "2.60"
end
it 'would update "auto_updates" and "latest" Casks when their tokens are provided in the command line' do
@ -295,34 +291,31 @@ describe Cask::Upgrade, :cask do
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.installed_version).to eq "1.2.2"
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57")
expect(auto_updates.installed_version).to eq "2.57"
expect(renamed_app).to be_installed
expect(renamed_app_old_path).to be_a_directory
expect(renamed_app_new_path).not_to be_a_directory
expect(renamed_app.versions).to include("1.0.0")
expect(renamed_app.installed_version).to eq "1.0.0"
described_class.upgrade_casks(local_caffeine, auto_updates, dry_run: true, args: args)
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.versions).not_to include("1.2.3")
expect(local_caffeine.installed_version).to eq "1.2.2"
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57")
expect(auto_updates.versions).not_to include("2.61")
expect(auto_updates.installed_version).to eq "2.57"
expect(renamed_app).to be_installed
expect(renamed_app_old_path).to be_a_directory
expect(renamed_app_new_path).not_to be_a_directory
expect(renamed_app.versions).to include("1.0.0")
expect(renamed_app.versions).not_to include("2.0.0")
expect(renamed_app.installed_version).to eq "1.0.0"
end
end
@ -332,20 +325,20 @@ describe Cask::Upgrade, :cask do
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.installed_version).to eq "1.2.2"
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57")
expect(auto_updates.installed_version).to eq "2.57"
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(local_transmission.installed_version).to eq "2.60"
expect(renamed_app).to be_installed
expect(renamed_app_old_path).to be_a_directory
expect(renamed_app_new_path).not_to be_a_directory
expect(renamed_app.versions).to include("1.0.0")
expect(renamed_app.installed_version).to eq "1.0.0"
expect(version_latest).to be_installed
# Change download sha so that :latest cask decides to update itself
@ -356,24 +349,20 @@ describe Cask::Upgrade, :cask do
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.versions).not_to include("1.2.3")
expect(local_caffeine.installed_version).to eq "1.2.2"
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57")
expect(auto_updates.versions).not_to include("2.61")
expect(auto_updates.installed_version).to eq "2.57"
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(local_transmission.versions).not_to include("2.61")
expect(local_transmission.installed_version).to eq "2.60"
expect(renamed_app).to be_installed
expect(renamed_app_old_path).to be_a_directory
expect(renamed_app_new_path).not_to be_a_directory
expect(renamed_app.versions).to include("1.0.0")
expect(renamed_app.versions).not_to include("2.0.0")
expect(renamed_app.installed_version).to eq "1.0.0"
expect(version_latest).to be_installed
expect(version_latest.outdated_download_sha?).to be(true)
@ -384,23 +373,21 @@ describe Cask::Upgrade, :cask do
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57")
expect(auto_updates.installed_version).to eq "2.57"
described_class.upgrade_casks(auto_updates, dry_run: true, greedy: true, args: args)
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57")
expect(auto_updates.versions).not_to include("2.61")
expect(auto_updates.installed_version).to eq "2.57"
end
it 'would update outdated Casks with "version latest"' do
expect(described_class).not_to receive(:upgrade_cask)
expect(version_latest).to be_installed
expect(version_latest_path_first).to be_a_directory
expect(version_latest_path_second).to be_a_directory
expect(version_latest.versions).to include("latest")
expect(version_latest_paths).to all be_a_directory
expect(version_latest.installed_version).to eq "latest"
# Change download sha so that :latest cask decides to update itself
version_latest.download_sha_path.write("fake download sha")
expect(version_latest.outdated_download_sha?).to be(true)
@ -408,9 +395,8 @@ describe Cask::Upgrade, :cask do
described_class.upgrade_casks(version_latest, dry_run: true, greedy: true, args: args)
expect(version_latest).to be_installed
expect(version_latest_path_first).to be_a_directory
expect(version_latest_path_second).to be_a_directory
expect(version_latest.versions).to include("latest")
expect(version_latest_paths).to all be_a_directory
expect(version_latest.installed_version).to eq "latest"
expect(version_latest.outdated_download_sha?).to be(true)
end
end
@ -440,7 +426,7 @@ describe Cask::Upgrade, :cask do
expect(will_fail_if_upgraded).to be_installed
expect(will_fail_if_upgraded_path).to be_a_file
expect(will_fail_if_upgraded.versions).to include("1.2.2")
expect(will_fail_if_upgraded.installed_version).to eq "1.2.2"
expect do
described_class.upgrade_casks(will_fail_if_upgraded, args: args)
@ -448,7 +434,7 @@ describe Cask::Upgrade, :cask do
expect(will_fail_if_upgraded).to be_installed
expect(will_fail_if_upgraded_path).to be_a_file
expect(will_fail_if_upgraded.versions).to include("1.2.2")
expect(will_fail_if_upgraded.installed_version).to eq "1.2.2"
expect(will_fail_if_upgraded.staged_path).not_to exist
end
@ -458,7 +444,7 @@ describe Cask::Upgrade, :cask do
expect(bad_checksum).to be_installed
expect(bad_checksum_path).to be_a_directory
expect(bad_checksum.versions).to include("1.2.2")
expect(bad_checksum.installed_version).to eq "1.2.2"
expect do
described_class.upgrade_casks(bad_checksum, args: args)
@ -466,7 +452,7 @@ describe Cask::Upgrade, :cask do
expect(bad_checksum).to be_installed
expect(bad_checksum_path).to be_a_directory
expect(bad_checksum.versions).to include("1.2.2")
expect(bad_checksum.installed_version).to eq "1.2.2"
expect(bad_checksum.staged_path).not_to exist
end
end
@ -495,15 +481,15 @@ describe Cask::Upgrade, :cask do
expect(bad_checksum).to be_installed
expect(bad_checksum_path).to be_a_directory
expect(bad_checksum.versions).to include("1.2.2")
expect(bad_checksum.installed_version).to eq "1.2.2"
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(local_transmission.installed_version).to eq "2.60"
expect(bad_checksum_2).to be_installed
expect(bad_checksum_2_path).to be_a_file
expect(bad_checksum_2.versions).to include("1.2.2")
expect(bad_checksum_2.installed_version).to eq "1.2.2"
expect do
described_class.upgrade_casks(args: args)
@ -511,16 +497,16 @@ describe Cask::Upgrade, :cask do
expect(bad_checksum).to be_installed
expect(bad_checksum_path).to be_a_directory
expect(bad_checksum.versions).to include("1.2.2")
expect(bad_checksum.installed_version).to eq "1.2.2"
expect(bad_checksum.staged_path).not_to exist
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.61")
expect(local_transmission.installed_version).to eq "2.61"
expect(bad_checksum_2).to be_installed
expect(bad_checksum_2_path).to be_a_file
expect(bad_checksum_2.versions).to include("1.2.2")
expect(bad_checksum_2.installed_version).to eq "1.2.2"
expect(bad_checksum_2.staged_path).not_to exist
end
end

View File

@ -4,17 +4,17 @@ require "cli/named_args"
def setup_unredable_formula(name)
error = FormulaUnreadableError.new(name, RuntimeError.new("testing"))
allow(Formulary).to receive(:factory).with(name, force_bottle: false, flags: []).and_raise(error)
allow(Formulary).to receive(:factory).with(name, force_bottle: false, flags: [], warn: true).and_raise(error)
end
def setup_unredable_cask(name)
error = Cask::CaskUnreadableError.new(name, "testing")
allow(Cask::CaskLoader).to receive(:load).with(name).and_raise(error)
allow(Cask::CaskLoader).to receive(:load).with(name, config: nil).and_raise(error)
allow(Cask::CaskLoader).to receive(:load).with(name, config: nil, warn: true).and_raise(error)
config = instance_double(Cask::Config)
allow(Cask::Config).to receive(:from_args).and_return(config)
allow(Cask::CaskLoader).to receive(:load).with(name, config: config).and_raise(error)
allow(Cask::CaskLoader).to receive(:load).with(name, config: config, warn: true).and_raise(error)
end
describe Homebrew::CLI::NamedArgs do

View File

@ -11,7 +11,7 @@ describe "brew migrate" do
install_and_rename_coretap_formula "testball1", "testball2"
expect { brew "migrate", "testball1" }
.to output(/Processing testball1 formula rename to testball2/).to_stdout
.to output(/Migrating formula testball1 to testball2/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end

View File

@ -1,6 +1,9 @@
{
"token": "everything",
"full_token": "everything",
"old_tokens": [
],
"tap": "homebrew/cask",
"name": [
"Everything"

View File

@ -9,7 +9,7 @@ module Test
allow(::Cask::CaskLoader).to receive(:for).and_call_original if call_original
loader = ::Cask::CaskLoader::FromInstanceLoader.new cask
allow(::Cask::CaskLoader).to receive(:for).with(ref).and_return(loader)
allow(::Cask::CaskLoader).to receive(:for).with(ref, warn: true).and_return(loader)
end
end
end

View File

@ -15,8 +15,8 @@ module Test
allow(Formulary).to receive(:loader_for).and_call_original if call_original
loader = double(get_formula: formula)
allow(Formulary).to receive(:loader_for).with(ref, from: :keg).and_return(loader)
allow(Formulary).to receive(:loader_for).with(ref, from: nil).and_return(loader)
allow(Formulary).to receive(:loader_for).with(ref, from: :keg, warn: false).and_return(loader)
allow(Formulary).to receive(:loader_for).with(ref, from: nil, warn: true).and_return(loader)
end
end
end