From a8829f25d3c2de4b7ca17c83f80bdd2907cf5f9a Mon Sep 17 00:00:00 2001
From: Nick Thomas <nick@gitlab.com>
Date: Tue, 20 Sep 2016 17:21:52 +0100
Subject: [PATCH] Use base SHA for patches and diffs

This commit changes the revisions used for diffs. The current behaviour is
to show all changes between current tip of master and tip of the MR, rather
than matching the output of the web frontend (which just shows the changes
in the MR). Switching from start_sha to base_sha fixes this.
---
 lib/gitlab/workhorse.rb           | 12 +++++-----
 spec/lib/gitlab/workhorse_spec.rb | 40 ++++++++++++++++++++++++++++---
 2 files changed, 43 insertions(+), 9 deletions(-)

diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb
index 60aae541d46..5d33f98e89e 100644
--- a/lib/gitlab/workhorse.rb
+++ b/lib/gitlab/workhorse.rb
@@ -60,7 +60,7 @@ module Gitlab
       def send_git_diff(repository, diff_refs)
         params = {
           'RepoPath'  => repository.path_to_repo,
-          'ShaFrom'   => diff_refs.start_sha,
+          'ShaFrom'   => diff_refs.base_sha,
           'ShaTo'     => diff_refs.head_sha
         }
 
@@ -73,7 +73,7 @@ module Gitlab
       def send_git_patch(repository, diff_refs)
         params = {
           'RepoPath'  => repository.path_to_repo,
-          'ShaFrom'   => diff_refs.start_sha,
+          'ShaFrom'   => diff_refs.base_sha,
           'ShaTo'     => diff_refs.head_sha
         }
 
@@ -107,15 +107,15 @@ module Gitlab
           bytes
         end
       end
-      
+
       def write_secret
         bytes = SecureRandom.random_bytes(SECRET_LENGTH)
-        File.open(secret_path, 'w:BINARY', 0600) do |f| 
+        File.open(secret_path, 'w:BINARY', 0600) do |f|
           f.chmod(0600)
           f.write(Base64.strict_encode64(bytes))
         end
       end
-      
+
       def verify_api_request!(request_headers)
         JWT.decode(
           request_headers[INTERNAL_API_REQUEST_HEADER],
@@ -128,7 +128,7 @@ module Gitlab
       def secret_path
         Rails.root.join('.gitlab_workhorse_secret')
       end
-      
+
       protected
 
       def encode(hash)
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index 6c7fa7e7c15..b5b685da904 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -1,8 +1,16 @@
 require 'spec_helper'
 
 describe Gitlab::Workhorse, lib: true do
-  let(:project) { create(:project) }
-  let(:subject) { Gitlab::Workhorse }
+  let(:project)    { create(:project) }
+  let(:repository) { project.repository }
+
+  def decode_workhorse_header(array)
+    key, value = array
+    command, encoded_params = value.split(":")
+    params = JSON.parse(Base64.urlsafe_decode64(encoded_params))
+
+    [key, command, params]
+  end
 
   describe ".send_git_archive" do
     context "when the repository doesn't have an archive file path" do
@@ -11,11 +19,37 @@ describe Gitlab::Workhorse, lib: true do
       end
 
       it "raises an error" do
-        expect { subject.send_git_archive(project.repository, ref: "master", format: "zip") }.to raise_error(RuntimeError)
+        expect { described_class.send_git_archive(project.repository, ref: "master", format: "zip") }.to raise_error(RuntimeError)
       end
     end
   end
 
+  describe '.send_git_patch' do
+    let(:diff_refs) { double(base_sha: "base", head_sha: "head") }
+    subject { described_class.send_git_patch(repository, diff_refs) }
+
+    it 'sets the header correctly' do
+      key, command, params = decode_workhorse_header(subject)
+
+      expect(key).to eq("Gitlab-Workhorse-Send-Data")
+      expect(command).to eq("git-format-patch")
+      expect(params).to eq("RepoPath" => repository.path_to_repo, "ShaFrom" => "base", "ShaTo" => "head")
+    end
+  end
+
+  describe '.send_git_diff' do
+    let(:diff_refs) { double(base_sha: "base", head_sha: "head") }
+    subject { described_class.send_git_patch(repository, diff_refs) }
+
+    it 'sets the header correctly' do
+      key, command, params = decode_workhorse_header(subject)
+
+      expect(key).to eq("Gitlab-Workhorse-Send-Data")
+      expect(command).to eq("git-format-patch")
+      expect(params).to eq("RepoPath" => repository.path_to_repo, "ShaFrom" => "base", "ShaTo" => "head")
+    end
+  end
+
   describe ".secret" do
     subject { described_class.secret }
 
-- 
GitLab