@@ -250,6 +250,7 @@ def caveats
250250 Pathname . new ( f . opt_bin ) . mkpath
251251 FileUtils . touch ( f . opt_bin /"foo" )
252252 FileUtils . chmod ( 0755 , f . opt_bin /"foo" )
253+ allow ( f ) . to receive ( :any_version_installed? ) . and_return ( true )
253254 allow_any_instance_of ( Object ) . to receive ( :which ) . and_call_original
254255 end
255256
@@ -291,6 +292,54 @@ def caveats
291292 expect ( described_class . new ( keg_only_f ) . caveats ) . not_to include ( "shadowed" )
292293 end
293294
295+ it "does not warn when the queried formula itself is not installed" do
296+ uninstalled_f = formula ( "foo@old" ) do
297+ url "foo-1.0"
298+ keg_only :versioned_formula
299+ end
300+ Pathname . new ( uninstalled_f . opt_bin ) . mkpath
301+ FileUtils . touch ( uninstalled_f . opt_bin /"foo" )
302+ FileUtils . chmod ( 0755 , uninstalled_f . opt_bin /"foo" )
303+
304+ sibling_keg_bin = HOMEBREW_CELLAR /"foo@2.0/2.0/bin"
305+ sibling_keg_bin . mkpath
306+ sibling_shadower = sibling_keg_bin /"foo"
307+ sibling_shadower . write ( "#!/bin/sh\n " )
308+ sibling_shadower . chmod ( 0755 )
309+
310+ allow ( uninstalled_f ) . to receive_messages ( versioned_formulae_names : [ "foo@2.0" ] ,
311+ unversioned_formula_name : "foo" ,
312+ any_version_installed? : false )
313+ allow_any_instance_of ( Object ) . to receive ( :which ) . with ( "foo" , ORIGINAL_PATHS ) . and_return ( sibling_shadower )
314+
315+ expect ( described_class . new ( uninstalled_f ) . caveats ) . not_to include ( "shadowed" )
316+ end
317+
318+ it "warns for a keg-only formula when a sibling keg is linked over it" do
319+ keg_only_f = formula ( "foo@1.0" ) do
320+ url "foo-1.0"
321+ keg_only :versioned_formula
322+ end
323+ Pathname . new ( keg_only_f . opt_bin ) . mkpath
324+ FileUtils . touch ( keg_only_f . opt_bin /"foo" )
325+ FileUtils . chmod ( 0755 , keg_only_f . opt_bin /"foo" )
326+
327+ sibling_keg_bin = HOMEBREW_CELLAR /"foo@2.0/2.0/bin"
328+ sibling_keg_bin . mkpath
329+ sibling_shadower = sibling_keg_bin /"foo"
330+ sibling_shadower . write ( "#!/bin/sh\n " )
331+ sibling_shadower . chmod ( 0755 )
332+
333+ allow ( keg_only_f ) . to receive_messages ( versioned_formulae_names : [ "foo@2.0" ] ,
334+ unversioned_formula_name : "foo" ,
335+ any_version_installed? : true )
336+ allow_any_instance_of ( Object ) . to receive ( :which ) . with ( "foo" , ORIGINAL_PATHS ) . and_return ( sibling_shadower )
337+
338+ caveats = described_class . new ( keg_only_f ) . caveats
339+ expect ( caveats ) . to include ( "foo (shadowed by #{ sibling_shadower } from foo@2.0)" )
340+ expect ( caveats ) . to include ( "Run `brew link foo@1.0`" )
341+ end
342+
294343 it "warns when a keg-only formula has been linked" do
295344 keg_only_f = formula do
296345 url "foo-1.0"
@@ -299,7 +348,7 @@ def caveats
299348 Pathname . new ( keg_only_f . opt_bin ) . mkpath
300349 FileUtils . touch ( keg_only_f . opt_bin /"foo" )
301350 FileUtils . chmod ( 0755 , keg_only_f . opt_bin /"foo" )
302- allow ( keg_only_f ) . to receive ( : linked?) . and_return ( true )
351+ allow ( keg_only_f ) . to receive_messages ( linked? : true , any_version_installed? : true )
303352 shadower = Pathname . new ( "/usr/local/bin/foo" )
304353 allow_any_instance_of ( Object ) . to receive ( :which ) . with ( "foo" , ORIGINAL_PATHS ) . and_return ( shadower )
305354 allow ( shadower ) . to receive ( :realpath ) . and_return ( shadower )
@@ -331,6 +380,47 @@ def caveats
331380
332381 expect ( described_class . new ( f ) . caveats ) . not_to include ( "HOMEBREW_NO_PATH_SHADOW_CHECK" )
333382 end
383+
384+ it "annotates sibling-keg shadowers with the keg name and adds a `brew link` hint" do
385+ sibling_keg_bin = HOMEBREW_CELLAR /"#{ f . name } @1.0/1.0/bin"
386+ sibling_keg_bin . mkpath
387+ sibling_shadower = sibling_keg_bin /"foo"
388+ sibling_shadower . write ( "#!/bin/sh\n " )
389+ sibling_shadower . chmod ( 0755 )
390+
391+ allow ( f ) . to receive_messages ( versioned_formulae_names : [ "#{ f . name } @1.0" ] , unversioned_formula_name : nil )
392+ allow_any_instance_of ( Object ) . to receive ( :which ) . with ( "foo" , ORIGINAL_PATHS ) . and_return ( sibling_shadower )
393+
394+ caveats = described_class . new ( f ) . caveats
395+ expect ( caveats ) . to include ( "shadowed by other linked Homebrew commands" )
396+ expect ( caveats ) . to include ( "foo (shadowed by #{ sibling_shadower } from #{ f . name } @1.0)" )
397+ expect ( caveats ) . to include ( "Run `brew link #{ f . name } `" )
398+ expect ( caveats ) . not_to include ( "earlier in your PATH" )
399+ end
400+
401+ it "annotates only the sibling line when shadowers are mixed" do
402+ Pathname . new ( f . opt_bin ) . mkpath
403+ FileUtils . touch ( f . opt_bin /"bar" )
404+ FileUtils . chmod ( 0755 , f . opt_bin /"bar" )
405+
406+ sibling_keg_bin = HOMEBREW_CELLAR /"#{ f . name } @1.0/1.0/bin"
407+ sibling_keg_bin . mkpath
408+ sibling_shadower = sibling_keg_bin /"foo"
409+ sibling_shadower . write ( "#!/bin/sh\n " )
410+ sibling_shadower . chmod ( 0755 )
411+
412+ bar_shadower = Pathname . new ( "/usr/local/bin/bar" )
413+ allow ( bar_shadower ) . to receive ( :realpath ) . and_return ( bar_shadower )
414+
415+ allow ( f ) . to receive_messages ( versioned_formulae_names : [ "#{ f . name } @1.0" ] , unversioned_formula_name : nil )
416+ allow_any_instance_of ( Object ) . to receive ( :which ) . with ( "foo" , ORIGINAL_PATHS ) . and_return ( sibling_shadower )
417+ allow_any_instance_of ( Object ) . to receive ( :which ) . with ( "bar" , ORIGINAL_PATHS ) . and_return ( bar_shadower )
418+
419+ caveats = described_class . new ( f ) . caveats
420+ expect ( caveats ) . to include ( "foo (shadowed by #{ sibling_shadower } from #{ f . name } @1.0)" )
421+ expect ( caveats ) . to include ( "bar (shadowed by #{ bar_shadower } )" )
422+ expect ( caveats ) . to include ( "Run `brew link #{ f . name } `" )
423+ end
334424 end
335425
336426 describe "shell completions" do
0 commit comments