forked from Homebrew/brew
-
Notifications
You must be signed in to change notification settings - Fork 1
/
link.rb
139 lines (119 loc) 路 3.86 KB
/
link.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# typed: true
# frozen_string_literal: true
require "ostruct"
require "caveats"
require "cli/parser"
require "unlink"
module Homebrew
extend T::Sig
module_function
sig { returns(CLI::Parser) }
def link_args
Homebrew::CLI::Parser.new do
description <<~EOS
Symlink all of <formula>'s installed files into Homebrew's prefix. This
is done automatically when you install formulae but can be useful for DIY
installations.
EOS
switch "--overwrite",
description: "Delete files that already exist in the prefix while linking."
switch "-n", "--dry-run",
description: "List files which would be linked or deleted by "\
"`brew link --overwrite` without actually linking or deleting any files."
switch "-f", "--force",
description: "Allow keg-only formulae to be linked."
switch "--HEAD",
description: "Link the HEAD version of the formula if it is installed."
named_args :installed_formula, min: 1
end
end
def link
args = link_args.parse
options = {
overwrite: args.overwrite?,
dry_run: args.dry_run?,
verbose: args.verbose?,
}
kegs = if args.HEAD?
args.named.to_kegs.group_by(&:name).map do |name, resolved_kegs|
head_keg = resolved_kegs.find { |keg| keg.version.head? }
if head_keg.blank?
opoo <<~EOS
No HEAD keg installed for #{name}
To install, run:
brew install --HEAD #{name}
EOS
end
head_keg
end.reject(&:blank?)
else
args.named.to_latest_kegs
end
kegs.freeze.each do |keg|
keg_only = Formulary.keg_only?(keg.rack)
if keg.linked?
opoo "Already linked: #{keg}"
name_and_flag = "#{"--HEAD " if args.HEAD?}#{"--force " if keg_only}#{keg.name}"
puts <<~EOS
To relink, run:
brew unlink #{keg.name} && brew link #{name_and_flag}
EOS
next
end
if args.dry_run?
if args.overwrite?
puts "Would remove:"
else
puts "Would link:"
end
keg.link(**options)
puts_keg_only_path_message(keg) if keg_only
next
end
formula = begin
keg.to_formula
rescue FormulaUnavailableError
# Not all kegs may belong to formulae e.g. with `brew diy`
nil
end
if keg_only
if Homebrew.default_prefix? && formula.present? && formula.keg_only_reason.by_macos?
caveats = Caveats.new(formula)
opoo <<~EOS
Refusing to link macOS provided/shadowed software: #{keg.name}
#{caveats.keg_only_text(skip_reason: true).strip}
EOS
next
end
if !args.force? && (formula.blank? || !formula.keg_only_reason.versioned_formula?)
opoo "#{keg.name} is keg-only and must be linked with `--force`."
puts_keg_only_path_message(keg)
next
end
end
Unlink.unlink_versioned_formulae(formula, verbose: args.verbose?) if formula
keg.lock do
print "Linking #{keg}... "
puts if args.verbose?
begin
n = keg.link(**options)
rescue Keg::LinkError
puts
raise
else
puts "#{n} symlinks created."
end
puts_keg_only_path_message(keg) if keg_only && !Homebrew::EnvConfig.developer?
end
end
end
def puts_keg_only_path_message(keg)
bin = keg/"bin"
sbin = keg/"sbin"
return if !bin.directory? && !sbin.directory?
opt = HOMEBREW_PREFIX/"opt/#{keg.name}"
puts "\nIf you need to have this software first in your PATH instead consider running:"
puts " #{Utils::Shell.prepend_path_in_profile(opt/"bin")}" if bin.directory?
puts " #{Utils::Shell.prepend_path_in_profile(opt/"sbin")}" if sbin.directory?
end
end