summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Speicher <robert@gitlab.com>2016-06-17 00:18:10 +0000
committerRobert Speicher <robert@gitlab.com>2016-06-17 00:18:10 +0000
commit6300936b679a182d79f6de917d1fdfe9ee57cbc9 (patch)
treed144a7006efac7e153bf730bffb4d5bbf49d8e3f
parent88c7b7ae961dc37d43ca29263d242241ce77efdb (diff)
parent425987861530c9c0fb7fe618d7f4bab017a80253 (diff)
downloadgitlab-ce-6300936b679a182d79f6de917d1fdfe9ee57cbc9.tar.gz
Merge branch 'fix-project-find-with-namespace-order' into 'master'
Fixed ordering in Project.find_with_namespace This MR fixes the ordering of `Project.find_with_namespace` to ensure that it returns rows that match literally first. Closes #18603 See merge request !4682
-rw-r--r--app/models/project.rb18
-rw-r--r--spec/models/project_spec.rb18
2 files changed, 34 insertions, 2 deletions
diff --git a/app/models/project.rb b/app/models/project.rb
index 0bb815e64e7..8eef22356e2 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -262,7 +262,23 @@ class Project < ActiveRecord::Base
#
# Returns a Project, or nil if no project could be found.
def find_with_namespace(path)
- where_paths_in([path]).reorder(nil).take
+ namespace_path, project_path = path.split('/', 2)
+
+ return unless namespace_path && project_path
+
+ namespace_path = connection.quote(namespace_path)
+ project_path = connection.quote(project_path)
+
+ # On MySQL we want to ensure the ORDER BY uses a case-sensitive match so
+ # any literal matches come first, for this we have to use "BINARY".
+ # Without this there's still no guarantee in what order MySQL will return
+ # rows.
+ binary = Gitlab::Database.mysql? ? 'BINARY' : ''
+
+ order_sql = "(CASE WHEN #{binary} namespaces.path = #{namespace_path} " \
+ "AND #{binary} projects.path = #{project_path} THEN 0 ELSE 1 END)"
+
+ where_paths_in([path]).reorder(order_sql).take
end
# Builds a relation to find multiple projects by their full paths.
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index fedab1f913b..53c8408633c 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -220,7 +220,7 @@ describe Project, models: true do
end
end
- describe :find_with_namespace do
+ describe '.find_with_namespace' do
context 'with namespace' do
before do
@group = create :group, name: 'gitlab'
@@ -231,6 +231,22 @@ describe Project, models: true do
it { expect(Project.find_with_namespace('GitLab/GitlabHQ')).to eq(@project) }
it { expect(Project.find_with_namespace('gitlab-ci')).to be_nil }
end
+
+ context 'when multiple projects using a similar name exist' do
+ let(:group) { create(:group, name: 'gitlab') }
+
+ let!(:project1) do
+ create(:empty_project, name: 'gitlab1', path: 'gitlab', namespace: group)
+ end
+
+ let!(:project2) do
+ create(:empty_project, name: 'gitlab2', path: 'GITLAB', namespace: group)
+ end
+
+ it 'returns the row where the path matches literally' do
+ expect(Project.find_with_namespace('gitlab/GITLAB')).to eq(project2)
+ end
+ end
end
describe :to_param do