FIX: handle force push and bad commit hash (#8)

FIX: handle force push and bad commit hash (#8)

diff --git a/lib/discourse_code_review/github_repo.rb b/lib/discourse_code_review/github_repo.rb
index a10512f..ff122bd 100644
--- a/lib/discourse_code_review/github_repo.rb
+++ b/lib/discourse_code_review/github_repo.rb
@@ -32,11 +32,17 @@ module DiscourseCodeReview
     end
 
     def last_commit
-      PluginStore.get(DiscourseCodeReview::PluginName, LastCommit + @name).presence ||
-        begin
-          commits = [SiteSetting.code_review_catch_up_commits, 1].max - 1
-          (self.last_commit = git("rev-parse HEAD~#{commits}", backup_command: 'rev-list --max-parents=0 HEAD'))
-        end
+      commit_hash = PluginStore.get(DiscourseCodeReview::PluginName, LastCommit + @name)
+      if commit_hash.present? && !commit_hash_valid?(commit_hash)
+        Rails.logger.warn("Discourse Code Review: Failed to detect commit hash `#{commit_hash}` in #{path}, resetting last commit hash.")
+        commit_hash = nil
+      end
+      if !commit_hash
+        commits = [SiteSetting.code_review_catch_up_commits, 1].max - 1
+        commit_hash = (self.last_commit = git("rev-parse HEAD~#{commits}", backup_command: 'rev-list --max-parents=0 HEAD'))
+      end
+
+      commit_hash
     end
 
     def last_commit=(v)
@@ -44,6 +50,12 @@ module DiscourseCodeReview
       v
     end
 
+    def commit_hash_valid?(hash)
+      git("cat-file -t #{hash}") == "commit"
+    rescue
+      false
+    end
+
     def commit_comments(page = nil)
       # TODO add a distributed lock here
       git("pull")
diff --git a/spec/discourse_code_review/lib/github_repo_spec.rb b/spec/discourse_code_review/lib/github_repo_spec.rb
index c9a6a19..c83368f 100644
--- a/spec/discourse_code_review/lib/github_repo_spec.rb
+++ b/spec/discourse_code_review/lib/github_repo_spec.rb
@@ -90,5 +90,30 @@ module DiscourseCodeReview
         expect(repo.last_commit).to eq(sha)
       end
     end
+
+    it "does not explode on force pushing (bad hash)" do
+      Dir.chdir(@git_path) do
+        `git init .`
+        File.write('a', 'hello')
+        `git add a`
+        `git commit -am 'first commit'`
+        File.write('a', 'hello2')
+        `git commit -am 'second commit'`
+
+        repo = GithubRepo.new('fake_repo/fake_repo', nil)
+        repo.path = @git_path
+
+        # mimic force push event
+        repo.last_commit = "98ab71e61d89149bac528e1d01b9c6d17e5f677a"
+
+        File.write('a', 'hello3')
+        `git commit -am 'third commit'`
+
+        SiteSetting.code_review_catch_up_commits = 1
+
+        sha = `git rev-parse HEAD~0`.strip
+        expect(repo.last_commit).to eq(sha)
+      end
+    end
   end
 end

GitHub sha: 0ff1942c

2 Likes