Refactor artifacts.
This commit is contained in:
parent
b38c52f930
commit
621b67e531
@ -32,10 +32,7 @@ module Hbc
|
|||||||
def self.read_script_arguments(arguments, stanza, default_arguments = {}, override_arguments = {}, key = nil)
|
def self.read_script_arguments(arguments, stanza, default_arguments = {}, override_arguments = {}, key = nil)
|
||||||
# TODO: when stanza names are harmonized with class names,
|
# TODO: when stanza names are harmonized with class names,
|
||||||
# stanza may not be needed as an explicit argument
|
# stanza may not be needed as an explicit argument
|
||||||
description = stanza.to_s
|
description = key ? "#{stanza} #{key.inspect}" : stanza.to_s
|
||||||
if key
|
|
||||||
description.concat(" #{key.inspect}")
|
|
||||||
end
|
|
||||||
|
|
||||||
# backward-compatible string value
|
# backward-compatible string value
|
||||||
arguments = { executable: arguments } if arguments.is_a?(String)
|
arguments = { executable: arguments } if arguments.is_a?(String)
|
||||||
|
|||||||
@ -7,8 +7,8 @@ module Hbc
|
|||||||
super if CLI.binaries?
|
super if CLI.binaries?
|
||||||
end
|
end
|
||||||
|
|
||||||
def link(artifact_spec)
|
def link
|
||||||
super(artifact_spec)
|
super
|
||||||
FileUtils.chmod "+x", source
|
FileUtils.chmod "+x", source
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -8,61 +8,38 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def install_phase
|
def install_phase
|
||||||
each_artifact do |artifact|
|
each_artifact(&method(:move))
|
||||||
load_specification(artifact)
|
|
||||||
next unless preflight_checks
|
|
||||||
delete if Utils.path_occupied?(target) && force
|
|
||||||
move
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def uninstall_phase
|
def uninstall_phase
|
||||||
each_artifact do |artifact|
|
each_artifact(&method(:delete))
|
||||||
load_specification(artifact)
|
|
||||||
next unless File.exist?(target)
|
|
||||||
delete
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def each_artifact
|
|
||||||
# the sort is for predictability between Ruby versions
|
|
||||||
@cask.artifacts[self.class.artifact_dsl_key].sort.each do |artifact|
|
|
||||||
yield artifact
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def move
|
def move
|
||||||
ohai "Moving #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'"
|
if Utils.path_occupied?(target)
|
||||||
|
message = "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'"
|
||||||
|
raise CaskError, "#{message}." unless force
|
||||||
|
opoo "#{message}; overwriting."
|
||||||
|
delete
|
||||||
|
end
|
||||||
|
|
||||||
|
unless source.exist?
|
||||||
|
raise CaskError, "It seems the #{self.class.artifact_english_name} source '#{source}' is not there."
|
||||||
|
end
|
||||||
|
|
||||||
|
ohai "Moving #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'."
|
||||||
target.dirname.mkpath
|
target.dirname.mkpath
|
||||||
FileUtils.move(source, target)
|
FileUtils.move(source, target)
|
||||||
add_altname_metadata target, source.basename.to_s
|
add_altname_metadata target, source.basename.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def preflight_checks
|
|
||||||
if Utils.path_occupied?(target)
|
|
||||||
raise CaskError, warning_target_exists << "." unless force
|
|
||||||
opoo(warning_target_exists { |s| s << "overwriting." })
|
|
||||||
end
|
|
||||||
unless source.exist?
|
|
||||||
message = "It seems the #{self.class.artifact_english_name} source is not there: '#{source}'"
|
|
||||||
raise CaskError, message
|
|
||||||
end
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def warning_target_exists
|
|
||||||
message_parts = [
|
|
||||||
"It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'",
|
|
||||||
]
|
|
||||||
yield(message_parts) if block_given?
|
|
||||||
message_parts.join("; ")
|
|
||||||
end
|
|
||||||
|
|
||||||
def delete
|
def delete
|
||||||
ohai "Removing #{self.class.artifact_english_name}: '#{target}'"
|
ohai "Removing #{self.class.artifact_english_name} '#{target}'."
|
||||||
raise CaskError, "Cannot remove undeletable #{self.class.artifact_english_name}" if MacOS.undeletable?(target)
|
return unless Utils.path_occupied?(target)
|
||||||
|
|
||||||
|
raise CaskError, "Cannot remove undeletable #{self.class.artifact_english_name}." if MacOS.undeletable?(target)
|
||||||
|
|
||||||
if force
|
if force
|
||||||
Utils.gain_permissions_remove(target, command: @command)
|
Utils.gain_permissions_remove(target, command: @command)
|
||||||
|
|||||||
@ -42,6 +42,14 @@ module Hbc
|
|||||||
print_stderr: false)
|
print_stderr: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def each_artifact
|
||||||
|
# the sort is for predictability between Ruby versions
|
||||||
|
@cask.artifacts[self.class.artifact_dsl_key].sort.each do |artifact|
|
||||||
|
load_specification(artifact)
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def load_specification(artifact_spec)
|
def load_specification(artifact_spec)
|
||||||
source_string, target_hash = artifact_spec
|
source_string, target_hash = artifact_spec
|
||||||
raise CaskInvalidError if source_string.nil?
|
raise CaskInvalidError if source_string.nil?
|
||||||
|
|||||||
@ -11,55 +11,48 @@ module Hbc
|
|||||||
"#{artifact_english_name} #{link_type_english_name}s"
|
"#{artifact_english_name} #{link_type_english_name}s"
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.islink?(path)
|
|
||||||
path.symlink?
|
|
||||||
end
|
|
||||||
|
|
||||||
def link(artifact_spec)
|
|
||||||
load_specification artifact_spec
|
|
||||||
return unless preflight_checks(source, target)
|
|
||||||
ohai "#{self.class.link_type_english_name}ing #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'"
|
|
||||||
create_filesystem_link(source, target)
|
|
||||||
end
|
|
||||||
|
|
||||||
def unlink(artifact_spec)
|
|
||||||
load_specification artifact_spec
|
|
||||||
return unless self.class.islink?(target)
|
|
||||||
ohai "Removing #{self.class.artifact_english_name} #{self.class.link_type_english_name.downcase}: '#{target}'"
|
|
||||||
target.delete
|
|
||||||
end
|
|
||||||
|
|
||||||
def install_phase
|
def install_phase
|
||||||
@cask.artifacts[self.class.artifact_dsl_key].each(&method(:link))
|
each_artifact(&method(:link))
|
||||||
end
|
end
|
||||||
|
|
||||||
def uninstall_phase
|
def uninstall_phase
|
||||||
@cask.artifacts[self.class.artifact_dsl_key].each(&method(:unlink))
|
each_artifact(&method(:unlink))
|
||||||
end
|
end
|
||||||
|
|
||||||
def preflight_checks(source, target)
|
private
|
||||||
if target.exist? && !self.class.islink?(target)
|
|
||||||
|
def link
|
||||||
|
unless source.exist?
|
||||||
|
raise CaskError, "It seems the #{self.class.link_type_english_name.downcase} source '#{source}' is not there."
|
||||||
|
end
|
||||||
|
|
||||||
|
if target.exist? && !target.symlink?
|
||||||
raise CaskError, "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'; not linking."
|
raise CaskError, "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'; not linking."
|
||||||
end
|
end
|
||||||
unless source.exist?
|
|
||||||
raise CaskError, "It seems the #{self.class.link_type_english_name.downcase} source is not there: '#{source}'"
|
ohai "Linking #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'."
|
||||||
end
|
create_filesystem_link(source, target)
|
||||||
true
|
end
|
||||||
|
|
||||||
|
def unlink
|
||||||
|
return unless target.symlink?
|
||||||
|
ohai "Unlinking #{self.class.artifact_english_name} '#{target}'."
|
||||||
|
target.delete
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_filesystem_link(source, target)
|
def create_filesystem_link(source, target)
|
||||||
Pathname.new(target).dirname.mkpath
|
target.dirname.mkpath
|
||||||
@command.run!("/bin/ln", args: ["-hfs", "--", source, target])
|
@command.run!("/bin/ln", args: ["-h", "-f", "-s", "--", source, target])
|
||||||
add_altname_metadata source, target.basename.to_s
|
add_altname_metadata source, target.basename.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def summarize_artifact(artifact_spec)
|
def summarize_artifact(artifact_spec)
|
||||||
load_specification artifact_spec
|
load_specification artifact_spec
|
||||||
|
|
||||||
if self.class.islink?(target) && target.exist? && target.readlink.exist?
|
if target.symlink? && target.exist? && target.readlink.exist?
|
||||||
"#{printable_target} -> #{target.readlink} (#{target.readlink.abv})"
|
"#{printable_target} -> #{target.readlink} (#{target.readlink.abv})"
|
||||||
else
|
else
|
||||||
string = if self.class.islink?(target)
|
string = if target.symlink?
|
||||||
"#{printable_target} -> #{target.readlink}"
|
"#{printable_target} -> #{target.readlink}"
|
||||||
else
|
else
|
||||||
printable_target
|
printable_target
|
||||||
|
|||||||
@ -7,8 +7,8 @@ describe Hbc::Artifact::App, :cask do
|
|||||||
let(:source_path) { cask.staged_path.join("Caffeine.app") }
|
let(:source_path) { cask.staged_path.join("Caffeine.app") }
|
||||||
let(:target_path) { Hbc.appdir.join("Caffeine.app") }
|
let(:target_path) { Hbc.appdir.join("Caffeine.app") }
|
||||||
|
|
||||||
let(:install_phase) { -> { app.install_phase } }
|
let(:install_phase) { app.install_phase }
|
||||||
let(:uninstall_phase) { -> { app.uninstall_phase } }
|
let(:uninstall_phase) { app.uninstall_phase }
|
||||||
|
|
||||||
before(:each) do
|
before(:each) do
|
||||||
InstallHelper.install_without_artifacts(cask)
|
InstallHelper.install_without_artifacts(cask)
|
||||||
@ -17,7 +17,7 @@ describe Hbc::Artifact::App, :cask do
|
|||||||
describe "install_phase" do
|
describe "install_phase" do
|
||||||
it "installs the given app using the proper target directory" do
|
it "installs the given app using the proper target directory" do
|
||||||
shutup do
|
shutup do
|
||||||
install_phase.call
|
install_phase
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(target_path).to be_a_directory
|
expect(target_path).to be_a_directory
|
||||||
@ -40,7 +40,7 @@ describe Hbc::Artifact::App, :cask do
|
|||||||
FileUtils.mv(source_path, appsubdir)
|
FileUtils.mv(source_path, appsubdir)
|
||||||
|
|
||||||
shutup do
|
shutup do
|
||||||
install_phase.call
|
install_phase
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(target_path).to be_a_directory
|
expect(target_path).to be_a_directory
|
||||||
@ -53,7 +53,7 @@ describe Hbc::Artifact::App, :cask do
|
|||||||
FileUtils.cp_r source_path, staged_app_copy
|
FileUtils.cp_r source_path, staged_app_copy
|
||||||
|
|
||||||
shutup do
|
shutup do
|
||||||
install_phase.call
|
install_phase
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(target_path).to be_a_directory
|
expect(target_path).to be_a_directory
|
||||||
@ -69,7 +69,7 @@ describe Hbc::Artifact::App, :cask do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "avoids clobbering an existing app" do
|
it "avoids clobbering an existing app" do
|
||||||
expect(install_phase).to raise_error(Hbc::CaskError, "It seems there is already an App at '#{target_path}'.")
|
expect { install_phase }.to raise_error(Hbc::CaskError, "It seems there is already an App at '#{target_path}'.")
|
||||||
|
|
||||||
expect(source_path).to be_a_directory
|
expect(source_path).to be_a_directory
|
||||||
expect(target_path).to be_a_directory
|
expect(target_path).to be_a_directory
|
||||||
@ -89,17 +89,17 @@ describe Hbc::Artifact::App, :cask do
|
|||||||
describe "target is both writable and user-owned" do
|
describe "target is both writable and user-owned" do
|
||||||
it "overwrites the existing app" do
|
it "overwrites the existing app" do
|
||||||
stdout = <<-EOS.undent
|
stdout = <<-EOS.undent
|
||||||
==> Removing App: '#{target_path}'
|
==> Removing App '#{target_path}'.
|
||||||
==> Moving App 'Caffeine.app' to '#{target_path}'
|
==> Moving App 'Caffeine.app' to '#{target_path}'.
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
stderr = <<-EOS.undent
|
stderr = <<-EOS.undent
|
||||||
Warning: It seems there is already an App at '#{target_path}'; overwriting.
|
Warning: It seems there is already an App at '#{target_path}'; overwriting.
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
expect {
|
expect { install_phase }
|
||||||
expect(install_phase).to output(stdout).to_stdout
|
.to output(stdout).to_stdout
|
||||||
}.to output(stderr).to_stderr
|
.and output(stderr).to_stderr
|
||||||
|
|
||||||
expect(source_path).not_to exist
|
expect(source_path).not_to exist
|
||||||
expect(target_path).to be_a_directory
|
expect(target_path).to be_a_directory
|
||||||
@ -124,17 +124,17 @@ describe Hbc::Artifact::App, :cask do
|
|||||||
.and_call_original
|
.and_call_original
|
||||||
|
|
||||||
stdout = <<-EOS.undent
|
stdout = <<-EOS.undent
|
||||||
==> Removing App: '#{target_path}'
|
==> Removing App '#{target_path}'.
|
||||||
==> Moving App 'Caffeine.app' to '#{target_path}'
|
==> Moving App 'Caffeine.app' to '#{target_path}'.
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
stderr = <<-EOS.undent
|
stderr = <<-EOS.undent
|
||||||
Warning: It seems there is already an App at '#{target_path}'; overwriting.
|
Warning: It seems there is already an App at '#{target_path}'; overwriting.
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
expect {
|
expect { install_phase }
|
||||||
expect(install_phase).to output(stdout).to_stdout
|
.to output(stdout).to_stdout
|
||||||
}.to output(stderr).to_stderr
|
.and output(stderr).to_stderr
|
||||||
|
|
||||||
expect(source_path).not_to exist
|
expect(source_path).not_to exist
|
||||||
expect(target_path).to be_a_directory
|
expect(target_path).to be_a_directory
|
||||||
@ -160,7 +160,7 @@ describe Hbc::Artifact::App, :cask do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "leaves the target alone" do
|
it "leaves the target alone" do
|
||||||
expect(install_phase).to raise_error(Hbc::CaskError, "It seems there is already an App at '#{target_path}'.")
|
expect { install_phase }.to raise_error(Hbc::CaskError, "It seems there is already an App at '#{target_path}'.")
|
||||||
expect(target_path).to be_a_symlink
|
expect(target_path).to be_a_symlink
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -169,17 +169,17 @@ describe Hbc::Artifact::App, :cask do
|
|||||||
|
|
||||||
it "overwrites the existing app" do
|
it "overwrites the existing app" do
|
||||||
stdout = <<-EOS.undent
|
stdout = <<-EOS.undent
|
||||||
==> Removing App: '#{target_path}'
|
==> Removing App '#{target_path}'.
|
||||||
==> Moving App 'Caffeine.app' to '#{target_path}'
|
==> Moving App 'Caffeine.app' to '#{target_path}'.
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
stderr = <<-EOS.undent
|
stderr = <<-EOS.undent
|
||||||
Warning: It seems there is already an App at '#{target_path}'; overwriting.
|
Warning: It seems there is already an App at '#{target_path}'; overwriting.
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
expect {
|
expect { install_phase }
|
||||||
expect(install_phase).to output(stdout).to_stdout
|
.to output(stdout).to_stdout
|
||||||
}.to output(stderr).to_stderr
|
.and output(stderr).to_stderr
|
||||||
|
|
||||||
expect(source_path).not_to exist
|
expect(source_path).not_to exist
|
||||||
expect(target_path).to be_a_directory
|
expect(target_path).to be_a_directory
|
||||||
@ -193,22 +193,22 @@ describe Hbc::Artifact::App, :cask do
|
|||||||
it "gives a warning if the source doesn't exist" do
|
it "gives a warning if the source doesn't exist" do
|
||||||
source_path.rmtree
|
source_path.rmtree
|
||||||
|
|
||||||
message = "It seems the App source is not there: '#{source_path}'"
|
message = "It seems the App source '#{source_path}' is not there."
|
||||||
|
|
||||||
expect(install_phase).to raise_error(Hbc::CaskError, message)
|
expect { install_phase }.to raise_error(Hbc::CaskError, message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "uninstall_phase" do
|
describe "uninstall_phase" do
|
||||||
it "deletes managed apps" do
|
it "deletes managed apps" do
|
||||||
shutup do
|
shutup do
|
||||||
install_phase.call
|
install_phase
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(target_path).to exist
|
expect(target_path).to exist
|
||||||
|
|
||||||
shutup do
|
shutup do
|
||||||
uninstall_phase.call
|
uninstall_phase
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(target_path).not_to exist
|
expect(target_path).not_to exist
|
||||||
@ -226,7 +226,7 @@ describe Hbc::Artifact::App, :cask do
|
|||||||
describe "app is correctly installed" do
|
describe "app is correctly installed" do
|
||||||
it "returns the path to the app" do
|
it "returns the path to the app" do
|
||||||
shutup do
|
shutup do
|
||||||
install_phase.call
|
install_phase
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(contents).to eq(["#{target_path} (#{target_path.abv})"])
|
expect(contents).to eq(["#{target_path} (#{target_path.abv})"])
|
||||||
|
|||||||
@ -47,6 +47,7 @@ describe Hbc::CLI::Uninstall, :cask do
|
|||||||
end
|
end
|
||||||
|
|
||||||
expect(cask).to be_installed
|
expect(cask).to be_installed
|
||||||
|
expect(Hbc.appdir.join("MyFancyApp.app")).to exist
|
||||||
|
|
||||||
expect {
|
expect {
|
||||||
shutup do
|
shutup do
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user