Install tap command completions and manpages

Taps can include completion scripts for external commands under
`completions/bash`, `completions/fish`, or `completions/zsh`. `brew tap`
will automatically install these into the correct directories during
install.
This commit is contained in:
Joshua McKinney 2016-09-30 18:22:53 -05:00
parent a74b7ade66
commit 25396d9c4d
7 changed files with 126 additions and 60 deletions

View File

@ -77,6 +77,7 @@ module Homebrew
lib/ruby/site_ruby/[12].*
lib/ruby/vendor_ruby/[12].*
manpages/brew.1
manpages/brew-cask.1
share/pypy/*
share/pypy3/*
share/info/dir

View File

@ -38,7 +38,7 @@ module Homebrew
def tap
if ARGV.include? "--repair"
Tap.each(&:link_manpages)
Tap.each(&:link_completions_and_manpages)
elsif ARGV.include? "--list-official"
require "official_taps"
puts OFFICIAL_TAPS.map { |t| "homebrew/#{t}" }

View File

@ -104,8 +104,8 @@ module Homebrew
puts if ARGV.include?("--preinstall")
end
link_completions_and_docs
Tap.each(&:link_manpages)
link_completions_manpages_and_docs
Tap.each(&:link_completions_and_manpages)
Homebrew.failed = true if ENV["HOMEBREW_UPDATE_FAILED"]
@ -281,7 +281,7 @@ module Homebrew
EOS
end
link_completions_and_docs(new_homebrew_repository)
link_completions_manpages_and_docs(new_homebrew_repository)
ohai "Migrated HOMEBREW_REPOSITORY to #{new_homebrew_repository}!"
puts <<-EOS.undent
@ -302,16 +302,11 @@ module Homebrew
$stderr.puts e.backtrace
end
def link_completions_and_docs(repository = HOMEBREW_REPOSITORY)
def link_completions_manpages_and_docs(repository = HOMEBREW_REPOSITORY)
command = "brew update"
link_src_dst_dirs(repository/"completions/bash",
HOMEBREW_PREFIX/"etc/bash_completion.d", command)
link_src_dst_dirs(repository/"docs",
HOMEBREW_PREFIX/"share/doc/homebrew", command, link_dir: true)
link_src_dst_dirs(repository/"completions/zsh",
HOMEBREW_PREFIX/"share/zsh/site-functions", command)
link_src_dst_dirs(repository/"manpages",
HOMEBREW_PREFIX/"share/man/man1", command)
Utils::Link.link_completions(repository, command)
Utils::Link.link_manpages(repository, command)
Utils::Link.link_docs(repository, command)
rescue => e
ofail <<-EOS.undent
Failed to link all completions, docs and manpages:

View File

@ -236,7 +236,7 @@ class Tap
raise
end
link_manpages
link_completions_and_manpages
formula_count = formula_files.size
puts "Tapped #{formula_count} formula#{plural(formula_count, "e")} (#{path.abv})" unless quiet
@ -254,8 +254,10 @@ class Tap
EOS
end
def link_manpages
link_path_manpages(path, "brew tap --repair")
def link_completions_and_manpages
command = "brew tap --repair"
Utils::Link.link_manpages(path, command)
Utils::Link.link_completions(path, command)
end
# uninstall this {Tap}.
@ -267,23 +269,14 @@ class Tap
unpin if pinned?
formula_count = formula_files.size
Descriptions.uncache_formulae(formula_names)
unlink_manpages
Utils::Link.unlink_manpages(path)
Utils::Link.unlink_completions(path)
path.rmtree
path.parent.rmdir_if_possible
puts "Untapped #{formula_count} formula#{plural(formula_count, "e")}"
clear_cache
end
def unlink_manpages
return unless (path/"man").exist?
(path/"man").find do |src|
next if src.directory?
dst = HOMEBREW_PREFIX/"share"/src.relative_path_from(path)
dst.delete if dst.symlink? && src == dst.resolved_path
dst.parent.rmdir_if_possible
end
end
# True if the {#remote} of {Tap} is customized.
def custom_remote?
return true unless remote

View File

@ -60,9 +60,18 @@ class TapTest < Homebrew::TestCase
@cmd_file.parent.mkpath
touch @cmd_file
chmod 0755, @cmd_file
@manpage_file = @path/"man/man1/brew-tap-cmd.1"
@manpage_file = @path/"manpages/brew-tap-cmd.1"
@manpage_file.parent.mkpath
touch @manpage_file
@bash_completion_file = @path/"completions/bash/brew-tap-cmd"
@bash_completion_file.parent.mkpath
touch @bash_completion_file
@zsh_completion_file = @path/"completions/zsh/_brew-tap-cmd"
@zsh_completion_file.parent.mkpath
touch @zsh_completion_file
@fish_completion_file = @path/"completions/fish/brew-tap-cmd.fish"
@fish_completion_file.parent.mkpath
touch @fish_completion_file
end
def setup_git_repo
@ -238,10 +247,39 @@ class TapTest < Homebrew::TestCase
shutup { tap.install clone_target: @tap.path/".git" }
assert_predicate tap, :installed?
assert_predicate HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1", :file?
assert_predicate HOMEBREW_PREFIX/"etc/bash_completion.d/brew-tap-cmd", :file?
assert_predicate HOMEBREW_PREFIX/"share/zsh/site-functions/_brew-tap-cmd", :file?
assert_predicate HOMEBREW_PREFIX/"share/fish/vendor_completions.d/brew-tap-cmd.fish", :file?
shutup { tap.uninstall }
refute_predicate tap, :installed?
refute_predicate HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1", :exist?
refute_predicate HOMEBREW_PREFIX/"share/man/man1", :exist?
refute_predicate HOMEBREW_PREFIX/"etc/bash_completion.d/brew-tap-cmd", :exist?
refute_predicate HOMEBREW_PREFIX/"share/zsh/site-functions/_brew-tap-cmd", :exist?
refute_predicate HOMEBREW_PREFIX/"share/fish/vendor_completions.d/brew-tap-cmd.fish", :exist?
ensure
(HOMEBREW_PREFIX/"etc").rmtree if (HOMEBREW_PREFIX/"etc").exist?
(HOMEBREW_PREFIX/"share").rmtree if (HOMEBREW_PREFIX/"share").exist?
end
def test_link_completions_and_manpages
setup_tap_files
setup_git_repo
tap = Tap.new("Homebrew", "baz")
shutup { tap.install clone_target: @tap.path/".git" }
(HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1").delete
(HOMEBREW_PREFIX/"etc/bash_completion.d/brew-tap-cmd").delete
(HOMEBREW_PREFIX/"share/zsh/site-functions/_brew-tap-cmd").delete
(HOMEBREW_PREFIX/"share/fish/vendor_completions.d/brew-tap-cmd.fish").delete
shutup { tap.link_completions_and_manpages }
assert_predicate HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1", :file?
assert_predicate HOMEBREW_PREFIX/"etc/bash_completion.d/brew-tap-cmd", :file?
assert_predicate HOMEBREW_PREFIX/"share/zsh/site-functions/_brew-tap-cmd", :file?
assert_predicate HOMEBREW_PREFIX/"share/fish/vendor_completions.d/brew-tap-cmd.fish", :file?
shutup { tap.uninstall }
ensure
(HOMEBREW_PREFIX/"etc").rmtree if (HOMEBREW_PREFIX/"etc").exist?
(HOMEBREW_PREFIX/"share").rmtree if (HOMEBREW_PREFIX/"share").exist?
end
def test_pin_and_unpin

View File

@ -9,6 +9,7 @@ require "utils/git"
require "utils/github"
require "utils/hash"
require "utils/inreplace"
require "utils/link"
require "utils/popen"
require "utils/tty"
require "time"
@ -481,38 +482,6 @@ def truncate_text_to_approximate_size(s, max_bytes, options = {})
out
end
def link_src_dst_dirs(src_dir, dst_dir, command, link_dir: false)
return unless src_dir.exist?
conflicts = []
src_paths = link_dir ? [src_dir] : src_dir.find
src_paths.each do |src|
next if src.directory? && !link_dir
dst = dst_dir/src.relative_path_from(src_dir)
if dst.symlink?
next if src == dst.resolved_path
dst.unlink
end
if dst.exist?
conflicts << dst
next
end
dst_dir.parent.mkpath
dst.make_relative_symlink(src)
end
return if conflicts.empty?
onoe <<-EOS.undent
Could not link:
#{conflicts.join("\n")}
Please delete these paths and run `#{command}`.
EOS
end
def link_path_manpages(path, command)
link_src_dst_dirs(path/"man", HOMEBREW_PREFIX/"share/man", command)
end
def migrate_legacy_keg_symlinks_if_necessary
legacy_linked_kegs = HOMEBREW_LIBRARY/"LinkedKegs"
return unless legacy_linked_kegs.directory?

View File

@ -0,0 +1,70 @@
module Utils
module Link
module_function
def link_src_dst_dirs(src_dir, dst_dir, command, link_dir: false)
return unless src_dir.exist?
conflicts = []
src_paths = link_dir ? [src_dir] : src_dir.find
src_paths.each do |src|
next if src.directory? && !link_dir
dst = dst_dir/src.relative_path_from(src_dir)
if dst.symlink?
next if src == dst.resolved_path
dst.unlink
end
if dst.exist?
conflicts << dst
next
end
dst_dir.parent.mkpath
dst.make_relative_symlink(src)
end
return if conflicts.empty?
onoe <<-EOS.undent
Could not link:
#{conflicts.join("\n")}
Please delete these paths and run `#{command}`.
EOS
end
private_class_method :link_src_dst_dirs
def unlink_src_dst_dirs(src_dir, dst_dir, unlink_dir: false)
return unless src_dir.exist?
src_paths = unlink_dir ? [src_dir] : src_dir.find
src_paths.each do |src|
next if src.directory? && !unlink_dir
dst = dst_dir/src.relative_path_from(src_dir)
dst.delete if dst.symlink? && src == dst.resolved_path
dst.parent.rmdir_if_possible
end
end
private_class_method :unlink_src_dst_dirs
def link_manpages(path, command)
link_src_dst_dirs(path/"manpages", HOMEBREW_PREFIX/"share/man/man1", command)
end
def unlink_manpages(path)
unlink_src_dst_dirs(path/"manpages", HOMEBREW_PREFIX/"share/man/man1")
end
def link_completions(path, command)
link_src_dst_dirs(path/"completions/bash", HOMEBREW_PREFIX/"etc/bash_completion.d", command)
link_src_dst_dirs(path/"completions/zsh", HOMEBREW_PREFIX/"share/zsh/site-functions", command)
link_src_dst_dirs(path/"completions/fish", HOMEBREW_PREFIX/"share/fish/vendor_completions.d", command)
end
def unlink_completions(path)
unlink_src_dst_dirs(path/"completions/bash", HOMEBREW_PREFIX/"etc/bash_completion.d")
unlink_src_dst_dirs(path/"completions/zsh", HOMEBREW_PREFIX/"share/zsh/site-functions")
unlink_src_dst_dirs(path/"completions/fish", HOMEBREW_PREFIX/"share/fish/vendor_completions.d")
end
def link_docs(path, command)
link_src_dst_dirs(path/"docs", HOMEBREW_PREFIX/"share/doc/homebrew", command, link_dir: true)
end
end
end