From d76416f5e8697341c1c32b0bf19101501300349d Mon Sep 17 00:00:00 2001
From: Grzegorz Bizon <grzesiek.bizon@gmail.com>
Date: Mon, 7 Nov 2016 13:33:33 +0100
Subject: [PATCH] Evade some exceptions when using invalid references

---
 app/models/repository.rb       |  6 ++++-
 spec/models/repository_spec.rb | 49 ++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/app/models/repository.rb b/app/models/repository.rb
index 30be7262438..f72f3157174 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -84,15 +84,17 @@ class Repository
 
   def commit(ref = 'HEAD')
     return nil unless exists?
+
     commit =
       if ref.is_a?(Gitlab::Git::Commit)
         ref
       else
         Gitlab::Git::Commit.find(raw_repository, ref)
       end
+
     commit = ::Commit.new(commit, @project) if commit
     commit
-  rescue Rugged::OdbError
+  rescue Rugged::OdbError,  Rugged::TreeError
     nil
   end
 
@@ -232,6 +234,8 @@ class Repository
 
   def ref_exists?(ref)
     rugged.references.exist?(ref)
+  rescue Rugged::ReferenceError
+    false
   end
 
   def update_ref!(name, newrev, oldrev)
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 04b7d19d414..f35de604c7a 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -113,6 +113,26 @@ describe Repository, models: true do
     end
   end
 
+  describe '#ref_exists?' do
+    context 'when ref exists' do
+      it 'returns true' do
+        expect(repository.ref_exists?('refs/heads/master')).to be true
+      end
+    end
+
+    context 'when ref does not exist' do
+      it 'returns false' do
+        expect(repository.ref_exists?('refs/heads/non-existent')).to be false
+      end
+    end
+
+    context 'when ref format is incorrect' do
+      it 'returns false' do
+        expect(repository.ref_exists?('refs/heads/invalid:master')).to be false
+      end
+    end
+  end
+
   describe '#last_commit_for_path' do
     subject { repository.last_commit_for_path(sample_commit.id, '.gitignore').id }
 
@@ -197,6 +217,35 @@ describe Repository, models: true do
     end
   end
 
+  describe '#commit' do
+    context 'when ref exists' do
+      it 'returns commit object' do
+        expect(repository.commit('master'))
+          .to be_an_instance_of Commit
+      end
+    end
+
+    context 'when ref does not exist' do
+      it 'returns nil' do
+        expect(repository.commit('non-existent-ref')).to be_nil
+      end
+    end
+
+    context 'when ref is not valid' do
+      context 'when preceding tree element exists' do
+        it 'returns nil' do
+          expect(repository.commit('master:ref')).to be_nil
+        end
+      end
+
+      context 'when preceding tree element does not exist' do
+        it 'returns nil' do
+          expect(repository.commit('non-existent:ref')).to be_nil
+        end
+      end
+    end
+  end
+
   describe "#commit_dir" do
     it "commits a change that creates a new directory" do
       expect do
-- 
GitLab