diff --git a/app/services/projects/detect_repository_languages_service.rb b/app/services/projects/detect_repository_languages_service.rb index d3680637217705fcc1546b5081780f27d8f7d2f5..811bdfa116e5db73f14d9b51b4a7dd1cbb3baaa4 100644 --- a/app/services/projects/detect_repository_languages_service.rb +++ b/app/services/projects/detect_repository_languages_service.rb @@ -8,6 +8,7 @@ class DetectRepositoryLanguagesService < BaseService def execute repository_languages = project.repository_languages detection = Gitlab::LanguageDetection.new(repository, repository_languages) + return unless dectection.detect! matching_programming_languages = ensure_programming_languages(detection) diff --git a/app/workers/detect_repository_languages_worker.rb b/app/workers/detect_repository_languages_worker.rb index 954d0f9336bd827165d019f0b38797d887a1e28c..71ee3ab2a39d740b97ae255e06b19e5de28bec72 100644 --- a/app/workers/detect_repository_languages_worker.rb +++ b/app/workers/detect_repository_languages_worker.rb @@ -12,16 +12,14 @@ class DetectRepositoryLanguagesWorker attr_reader :project - # rubocop: disable CodeReuse/ActiveRecord def perform(project_id, user_id = nil) - @project = Project.find_by(id: project_id) + @project = Project.find_by_id(project_id) return unless project try_obtain_lease do ::Projects::DetectRepositoryLanguagesService.new(project).execute end end - # rubocop: enable CodeReuse/ActiveRecord private diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 4971a18e270800c3e022365d0b4e3b49e083773c..9ac0f6e70f216561a919ce350d30250c6a6863f1 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -727,7 +727,7 @@ def attributes_at(ref) AttributesAtRefParser.new(self, ref) end - def languages(ref = nil) + def languages(ref) wrapped_gitaly_errors do gitaly_commit_client.languages(ref) end diff --git a/lib/gitlab/language_detection.rb b/lib/gitlab/language_detection.rb index 7600e60b904e5dac6c6486177b79ee4746021b5e..b939cfd9430a25db673f39a3de917872005cbe36 100644 --- a/lib/gitlab/language_detection.rb +++ b/lib/gitlab/language_detection.rb @@ -9,6 +9,15 @@ def initialize(repository, repository_languages) @repository_languages = repository_languages end + # Gitaly will raise a FailedPrecondition if the language detection is fresh enough it's not worth the effort to + # detect again. + def detect! + detection + true + rescue GRPC::FailedPrecondition + false + end + def languages detection.keys end diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index 20a74af7a45a8d0b419653599267963b387e6301..40c524a8d924c090126d7e8efa271f1e5c859420 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -1503,7 +1503,7 @@ def commit_files(commit) end it "uses the repository's HEAD when no ref is passed" do - lang = repository.languages.first + lang = repository.languages('HEAD').first expect(lang[:label]).to eq('Ruby') end diff --git a/spec/lib/gitlab/language_detection_spec.rb b/spec/lib/gitlab/language_detection_spec.rb index f558ce0d527bdbc1c3f2727687c26bd98c847c30..afdb24f330187a7e22ac482bb43cdda36b687cc9 100644 --- a/spec/lib/gitlab/language_detection_spec.rb +++ b/spec/lib/gitlab/language_detection_spec.rb @@ -25,6 +25,24 @@ allow(repository).to receive(:languages).and_return(detection) end + describe '#detect!' do + context 'when Gitaly returns results' do + it 'returns true' do + expect(subject.detect!).to eq(true) + end + end + + context 'when Gitaly raises a FailedPrecondition' do + before do + allow(repository).to receive(:languages).and_raise(GRPC::FailedPrecondition) + end + + it 'returns false' do + expect(subject.detect!).to eq(false) + end + end + end + describe '#languages' do it 'returns the language names' do expect(subject.languages).to eq(%w[Ruby JavaScript Elixir CoffeeScript Go])