From dac66c4ada178c09b3b9b77feb2eaa7442b7443e Mon Sep 17 00:00:00 2001
From: Mike McQuaid <mike@mikemcquaid.com>
Date: Tue, 17 Jan 2017 10:43:43 +0000
Subject: [PATCH] Add `keg_only :versioned_formula`.

This is used to indicate a formula is a version of another formula.
This will be used to provide a consistent interface for older formulae
versions and replaces the use of `conflicts_with`.
---
 Library/Homebrew/dev-cmd/audit.rb   | 10 +++++-
 Library/Homebrew/formula.rb         |  5 +++
 Library/Homebrew/formula_support.rb | 47 ++++++++++++++++-------------
 docs/Versions.md                    |  2 +-
 4 files changed, 41 insertions(+), 23 deletions(-)

diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb
index 394e0e763d..2818396219 100644
--- a/Library/Homebrew/dev-cmd/audit.rb
+++ b/Library/Homebrew/dev-cmd/audit.rb
@@ -459,6 +459,14 @@ class FormulaAuditor
   end
 
   def audit_conflicts
+    if formula.versioned_formula?
+      problem <<-EOS
+        Versioned formulae should not use `conflicts_with`.
+        Use `keg_only :versioned_formula` instead.
+      EOS
+      return
+    end
+
     formula.conflicts.each do |c|
       begin
         Formulary.factory(c.name)
@@ -497,7 +505,7 @@ class FormulaAuditor
 
     return unless @new_formula
     return if formula.deprecated_options.empty?
-    return if formula.name.include?("@")
+    return if formula.versioned_formula?
     problem "New formulae should not use `deprecated_option`."
   end
 
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index 1ced5030fc..77688840c2 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -382,6 +382,11 @@ class Formula
     PkgVersion.new(version, revision)
   end
 
+  # If this is a `@`-versioned formula.
+  def versioned_formula?
+    name.include?("@")
+  end
+
   # A named Resource for the currently active {SoftwareSpec}.
   # Additional downloads can be defined as {#resource}s.
   # {Resource#stage} will create a temporary directory and yield to a block.
diff --git a/Library/Homebrew/formula_support.rb b/Library/Homebrew/formula_support.rb
index e4f8003644..dcb995a6be 100644
--- a/Library/Homebrew/formula_support.rb
+++ b/Library/Homebrew/formula_support.rb
@@ -29,27 +29,32 @@ class KegOnlyReason
   def to_s
     return @explanation unless @explanation.empty?
     case @reason
-    when :provided_by_macos, :provided_by_osx then <<-EOS
-macOS already provides this software and installing another version in
-parallel can cause all kinds of trouble.
-EOS
-    when :shadowed_by_macos, :shadowed_by_osx then <<-EOS
-macOS provides similar software and installing this software in
-parallel can cause all kinds of trouble.
-EOS
-    when :provided_pre_mountain_lion then <<-EOS
-macOS already provides this software in versions before Mountain Lion.
-EOS
-    when :provided_pre_mavericks then <<-EOS
-macOS already provides this software in versions before Mavericks.
-EOS
-    when :provided_pre_el_capitan then <<-EOS
-macOS already provides this software in versions before El Capitan.
-EOS
-    when :provided_until_xcode43
-      "Xcode provides this software prior to version 4.3."
-    when :provided_until_xcode5
-      "Xcode provides this software prior to version 5."
+    when :versioned_formula then <<-EOS.undent
+      This is an alternate version of another formula.
+    EOS
+    when :provided_by_macos, :provided_by_osx then <<-EOS.undent
+      macOS already provides this software and installing another version in
+      parallel can cause all kinds of trouble.
+    EOS
+    when :shadowed_by_macos, :shadowed_by_osx then <<-EOS.undent
+      macOS provides similar software and installing this software in
+      parallel can cause all kinds of trouble.
+    EOS
+    when :provided_pre_mountain_lion then <<-EOS.undent
+      macOS already provides this software in versions before Mountain Lion.
+    EOS
+    when :provided_pre_mavericks then <<-EOS.undent
+      macOS already provides this software in versions before Mavericks.
+    EOS
+    when :provided_pre_el_capitan then <<-EOS.undent
+      macOS already provides this software in versions before El Capitan.
+    EOS
+    when :provided_until_xcode43 then <<-EOS.undent
+      Xcode provides this software prior to version 4.3.
+    EOS
+    when :provided_until_xcode5 then <<-EOS.undent
+      Xcode provides this software prior to version 5.
+    EOS
     else
       @reason
     end.strip
diff --git a/docs/Versions.md b/docs/Versions.md
index 9e679db7dd..bd3ef8a5f8 100644
--- a/docs/Versions.md
+++ b/docs/Versions.md
@@ -11,6 +11,6 @@ Versioned formulae we include must meet the following standards:
 
 * Versioned formulae should differ in major/minor (not patch) versions from the current stable release. This is because patch versions indicate bug or security updates and we want to ensure you apply security updates.
 * Formulae that depend on versioned formulae must not depend on the same formulae at two different versions twice in their recursive dependencies. For example, if you depend on `openssl@1.0` and `foo`, and `foo` depends on `openssl` then you must instead use `openssl`.
-* Versioned formulae should strive to be linked at the same time as their non-versioned counterpart (without patching). If this is not possible, favour either `conflicts_with` or `keg_only` depending on whether users expect to have multiple versions installed at once or not.
+* Versioned formulae should only be linkable at the same time as their non-versioned counterpart if the upstream project provides support for e.g. suffixed binaries. If this is not possible, use `keg_only :versioned_formula` to allow users to have multiple versions installed at once.
 
 You should create your own [tap](https://github.com/Homebrew/brew/blob/master/docs/How-to-Create-and-Maintain-a-Tap.md) for formulae you or your organisation wishes to control the versioning of or those that do not meet the above standards.
-- 
GitLab