124 lines
3.1 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
2019-02-02 17:11:37 +01:00
require "json"
2017-12-03 09:06:23 +01:00
2019-02-03 02:40:27 +01:00
require "extend/hash_validator"
using HashValidator
2019-02-02 17:11:37 +01:00
module Cask
2019-02-03 02:40:27 +01:00
class Config
2019-02-02 17:11:37 +01:00
DEFAULT_DIRS = {
2019-02-05 16:08:29 +01:00
appdir: "/Applications",
prefpanedir: "~/Library/PreferencePanes",
qlplugindir: "~/Library/QuickLook",
2020-04-05 15:30:37 +02:00
mdimporterdir: "~/Library/Spotlight",
2019-02-05 16:08:29 +01:00
dictionarydir: "~/Library/Dictionaries",
fontdir: "~/Library/Fonts",
colorpickerdir: "~/Library/ColorPickers",
servicedir: "~/Library/Services",
input_methoddir: "~/Library/Input Methods",
internet_plugindir: "~/Library/Internet Plug-Ins",
audio_unit_plugindir: "~/Library/Audio/Plug-Ins/Components",
vst_plugindir: "~/Library/Audio/Plug-Ins/VST",
vst3_plugindir: "~/Library/Audio/Plug-Ins/VST3",
screen_saverdir: "~/Library/Screen Savers",
2019-02-02 17:11:37 +01:00
}.freeze
2017-12-03 09:06:23 +01:00
2019-02-02 17:11:37 +01:00
def self.global
@global ||= new
end
2017-12-03 09:06:23 +01:00
2019-02-03 02:40:27 +01:00
def self.clear
@global = nil
end
2019-02-02 17:11:37 +01:00
def self.for_cask(cask)
if cask.config_path.exist?
from_file(cask.config_path)
else
global
end
2017-12-03 09:06:23 +01:00
end
2019-02-02 17:11:37 +01:00
def self.from_file(path)
config = begin
JSON.parse(File.read(path))
rescue JSON::ParserError => e
raise e, "Cannot parse #{path}: #{e}", e.backtrace
end
2019-02-03 02:40:27 +01:00
new(
2019-02-05 16:08:29 +01:00
default: config.fetch("default", {}),
env: config.fetch("env", {}),
explicit: config.fetch("explicit", {}),
2019-02-03 02:40:27 +01:00
)
end
2019-02-05 16:08:29 +01:00
def self.canonicalize(config)
config.map do |k, v|
key = k.to_sym
if DEFAULT_DIRS.key?(key)
[key, Pathname(v).expand_path]
else
[key, v]
end
end.to_h
2019-02-05 16:08:29 +01:00
end
2019-02-03 02:40:27 +01:00
attr_accessor :explicit
def initialize(default: nil, env: nil, explicit: {})
Fix cask loading after adding an artifact type This commit fixes an issue where we added a new global artifact and then updated a cask to make use of that new artifact. This caused a number of `brew cask` commands to fail for users who had the cask installed before the artifact was added. When loading the definition of an installed cask, we configure it using a snapshot from install time, e. g. `/usr/local/Caskroom/markdownmdimporter/.metadata/config.json`. The snapshot looks like this: ``` { "default": { "appdir": "/Applications", "prefpanedir": "/Users/claudia/Library/PreferencePanes", "qlplugindir": "/Users/claudia/Library/QuickLook", "dictionarydir": "/Users/claudia/Library/Dictionaries", "fontdir": "/Users/claudia/Library/Fonts", "colorpickerdir": "/Users/claudia/Library/ColorPickers", "servicedir": "/Users/claudia/Library/Services", "input_methoddir": "/Users/claudia/Library/Input Methods", "internet_plugindir": "/Users/claudia/Library/Internet Plug-Ins", "audio_unit_plugindir": "/Users/claudia/Library/Audio/Plug-Ins/Components", "vst_plugindir": "/Users/claudia/Library/Audio/Plug-Ins/VST", "vst3_plugindir": "/Users/claudia/Library/Audio/Plug-Ins/VST3", "screen_saverdir": "/Users/claudia/Library/Screen Savers" }, "env": {}, "explicit": {} } ``` Note that there is no `mdimporterdir` because the cask was installed before the artifact was added. The root cause is that the cask loading code still expects the snapshot to contain directory configuration for all artifact types. Since the snapshot never learned about the new artifact type, cask loading would fail. The fix applied in this commit is to fall back to the global default whenever the `default` directory map of a configuration snapshot is incomplete. See also: - https://github.com/Homebrew/brew/pull/7286#issuecomment-613376568 - https://discourse.brew.sh/t/cask-definition-is-invalid-invalid-mdimporter-stanza-key-not-found-mdimporterdir
2020-04-21 17:45:34 +02:00
@default = DEFAULT_DIRS.merge(self.class.canonicalize(default)) if default
2019-02-05 16:08:29 +01:00
@env = self.class.canonicalize(env) if env
@explicit = self.class.canonicalize(explicit)
2019-02-03 02:40:27 +01:00
2019-02-05 16:08:29 +01:00
@env&.assert_valid_keys!(*DEFAULT_DIRS.keys)
@explicit.assert_valid_keys!(*DEFAULT_DIRS.keys)
2019-02-02 17:11:37 +01:00
end
2019-02-03 02:40:27 +01:00
def default
2019-02-05 16:08:29 +01:00
@default ||= self.class.canonicalize(DEFAULT_DIRS)
2019-02-03 02:40:27 +01:00
end
def env
2019-02-05 16:08:29 +01:00
@env ||= self.class.canonicalize(
Shellwords.shellsplit(ENV.fetch("HOMEBREW_CASK_OPTS", ""))
.select { |arg| arg.include?("=") }
.map { |arg| arg.split("=", 2) }
.map { |(flag, value)| [flag.sub(/^\-\-/, ""), value] },
)
2019-02-02 17:11:37 +01:00
end
def binarydir
@binarydir ||= HOMEBREW_PREFIX/"bin"
end
2019-10-22 15:19:40 +03:00
def manpagedir
@manpagedir ||= HOMEBREW_PREFIX/"share/man"
end
2020-02-19 11:18:40 +00:00
DEFAULT_DIRS.each_key do |dir|
2019-02-02 17:11:37 +01:00
define_method(dir) do
2019-02-03 02:40:27 +01:00
explicit.fetch(dir, env.fetch(dir, default.fetch(dir)))
2019-02-02 17:11:37 +01:00
end
2017-12-03 09:06:23 +01:00
define_method(:"#{dir}=") do |path|
2019-02-03 02:40:27 +01:00
explicit[dir] = Pathname(path).expand_path
2017-12-03 09:06:23 +01:00
end
end
2019-02-02 17:11:37 +01:00
2019-02-03 02:40:27 +01:00
def merge(other)
self.class.new(explicit: other.explicit.merge(explicit))
2019-02-03 02:40:27 +01:00
end
def to_json(*args)
{
default: default,
env: env,
explicit: explicit,
}.to_json(*args)
end
2017-12-03 09:06:23 +01:00
end
end