Commit fed399c4 authored by Andreas Brandl's avatar Andreas Brandl

Merge branch '51759-filter-by-language' into 'master'

Add programming language filtering to `/projects`

Closes #51759

See merge request gitlab-org/gitlab-ce!24377
parents 6b0b14f8 b421bd31
......@@ -3,4 +3,10 @@
class ProgrammingLanguage < ActiveRecord::Base
validates :name, presence: true
validates :color, allow_blank: false, color: true
# Returns all programming languages which match the given name (case
# insensitively).
scope :with_name_case_insensitive, ->(name) do
where(arel_table[:name].matches(sanitize_sql_like(name)))
end
end
......@@ -389,6 +389,16 @@ class Project < ActiveRecord::Base
with_project_feature.where(project_features: { access_level_attribute => level })
}
# Picks projects which use the given programming language
scope :with_programming_language, ->(language_name) do
lang_id_query = ProgrammingLanguage
.with_name_case_insensitive(language_name)
.select(:id)
joins(:repository_languages)
.where(repository_languages: { programming_language_id: lang_id_query })
end
scope :with_builds_enabled, -> { with_feature_enabled(:builds) }
scope :with_issues_enabled, -> { with_feature_enabled(:issues) }
scope :with_issues_available_for_user, ->(current_user) { with_feature_available_for_user(:issues, current_user) }
......
---
title: Add `with_programming_language` filter for projects to API
merge_request: 24377
author: Dylan MacKenzie
type: added
......@@ -54,6 +54,7 @@ GET /projects
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
| `with_issues_enabled` | boolean | no | Limit by enabled issues feature |
| `with_merge_requests_enabled` | boolean | no | Limit by enabled merge requests feature |
| `with_programming_language` | string | no | Limit by projects which use the given programming language |
| `wiki_checksum_failed` | boolean | no | Limit projects where the wiki checksum calculation has failed _([Introduced][ee-6137] in [GitLab Premium][eep] 11.2)_ |
| `repository_checksum_failed` | boolean | no | Limit projects where the repository checksum calculation has failed _([Introduced][ee-6137] in [GitLab Premium][eep] 11.2)_ |
| `min_access_level` | integer | no | Limit by current user minimal [access level](members.md) |
......@@ -279,6 +280,7 @@ GET /users/:user_id/projects
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
| `with_issues_enabled` | boolean | no | Limit by enabled issues feature |
| `with_merge_requests_enabled` | boolean | no | Limit by enabled merge requests feature |
| `with_programming_language` | string | no | Limit by projects which use the given programming language |
| `min_access_level` | integer | no | Limit by current user minimal [access level](members.md) |
```json
......
......@@ -25,6 +25,9 @@ module API
projects = projects.with_merge_requests_enabled if params[:with_merge_requests_enabled]
projects = projects.with_statistics if params[:statistics]
lang = params[:with_programming_language]
projects = projects.with_programming_language(lang) if lang
projects
end
......@@ -91,6 +94,7 @@ module API
optional :membership, type: Boolean, default: false, desc: 'Limit by projects that the current user is a member of'
optional :with_issues_enabled, type: Boolean, default: false, desc: 'Limit by enabled issues feature'
optional :with_merge_requests_enabled, type: Boolean, default: false, desc: 'Limit by enabled merge requests feature'
optional :with_programming_language, type: String, desc: 'Limit to repositories which use the given programming language'
optional :min_access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'Limit by minimum access level of authenticated user'
use :optional_filter_params_ee
......
......@@ -49,6 +49,27 @@ describe API::Projects do
namespace: user4.namespace)
end
shared_context 'with language detection' do
let(:ruby) { create(:programming_language, name: 'Ruby') }
let(:javascript) { create(:programming_language, name: 'JavaScript') }
let(:html) { create(:programming_language, name: 'HTML') }
let(:mock_repo_languages) do
{
project => { ruby => 0.5, html => 0.5 },
project3 => { html => 0.7, javascript => 0.3 }
}
end
before do
mock_repo_languages.each do |proj, lang_shares|
lang_shares.each do |lang, share|
create(:repository_language, project: proj, programming_language: lang, share: share)
end
end
end
end
describe 'GET /projects' do
shared_examples_for 'projects response' do
it 'returns an array of projects' do
......@@ -344,6 +365,19 @@ describe API::Projects do
end
end
context 'and using the programming language filter' do
include_context 'with language detection'
it 'filters case-insensitively by programming language' do
get api('/projects', user), params: { with_programming_language: 'javascript' }
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.map { |p| p['id'] }).to contain_exactly(project3.id)
end
end
context 'and using sorting' do
it 'returns the correct order when sorted by id' do
get api('/projects', user), params: { order_by: 'id', sort: 'desc' }
......@@ -755,6 +789,19 @@ describe API::Projects do
expect(json_response).to be_an Array
expect(json_response.map { |project| project['id'] }).to contain_exactly(private_project1.id)
end
context 'and using the programming language filter' do
include_context 'with language detection'
it 'filters case-insensitively by programming language' do
get api('/projects', user), params: { with_programming_language: 'ruby' }
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.map { |p| p['id'] }).to contain_exactly(project.id)
end
end
end
describe 'POST /projects/user/:id' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment