From b6a0105b7ec12544aaa0f3f75fa0f07993bdcab4 Mon Sep 17 00:00:00 2001
From: Mike McQuaid <mike@mikemcquaid.com>
Date: Sat, 7 Mar 2015 14:59:30 +0000
Subject: [PATCH] download_strategy: raise on wrong tag revision.

Adds some added security to Git tags so we are able to provide an
effective checksum rather than letting them be changed without our
knowing.

Also:

- Reprioritise ref_types. Tag should take priority over branch and revisions over a single one.
- Add current_revision method. Used to verify the current repository revision matches the specified
revision. Currently only implemented for Git.
---
 Library/Homebrew/download_strategy.rb | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb
index 42dde83152..08dfdcd78f 100644
--- a/Library/Homebrew/download_strategy.rb
+++ b/Library/Homebrew/download_strategy.rb
@@ -98,11 +98,12 @@ class AbstractDownloadStrategy
 end
 
 class VCSDownloadStrategy < AbstractDownloadStrategy
-  REF_TYPES = [:branch, :revision, :revisions, :tag].freeze
+  REF_TYPES = [:tag, :branch, :revisions, :revision].freeze
 
   def initialize name, resource
     super
     @ref_type, @ref = extract_ref(meta)
+    @revision = meta[:revision]
     @clone = HOMEBREW_CACHE.join(cache_filename)
   end
 
@@ -119,6 +120,15 @@ class VCSDownloadStrategy < AbstractDownloadStrategy
     else
       clone_repo
     end
+
+    if @ref_type == :tag && @revision && current_revision
+      unless current_revision == @revision
+        raise <<-EOS.undent
+          #{@ref} tag should be #{@revision}
+          but is actually #{current_revision}!
+        EOS
+      end
+    end
   end
 
   def stage
@@ -153,6 +163,9 @@ class VCSDownloadStrategy < AbstractDownloadStrategy
   def update
   end
 
+  def current_revision
+  end
+
   def extract_ref(specs)
     key = REF_TYPES.find { |type| specs.key?(type) }
     return key, specs[key]
@@ -570,6 +583,10 @@ class GitDownloadStrategy < VCSDownloadStrategy
     quiet_system 'git', '--git-dir', git_dir, 'rev-parse', '-q', '--verify', "#{@ref}^{commit}"
   end
 
+  def current_revision
+    Utils.popen_read('git', '--git-dir', git_dir, 'rev-parse', '-q', '--verify', "HEAD").strip
+  end
+
   def repo_valid?
     quiet_system "git", "--git-dir", git_dir, "status", "-s"
   end
-- 
GitLab