summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouwe Maan <douwe@gitlab.com>2015-10-20 16:16:08 +0200
committerDouwe Maan <douwe@gitlab.com>2015-10-20 16:16:08 +0200
commit2f7fc7e9f7e7a43914abe81a510bd0dffa113979 (patch)
tree58a5e745f1d11d1ada904fc69193c2ef25de7279
parent97eafd4b3dbc186fc3d633c20a7e364ebf31849d (diff)
downloadgitlab-ce-2f7fc7e9f7e7a43914abe81a510bd0dffa113979.tar.gz
Prefer project with exact path to differently cased one when both exist.
-rw-r--r--app/controllers/application_controller.rb4
-rw-r--r--app/models/project.rb17
-rw-r--r--spec/controllers/projects_controller_spec.rb30
3 files changed, 38 insertions, 13 deletions
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index f0124c6bd60..38e6b44eb6f 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -118,8 +118,8 @@ class ApplicationController < ActionController::Base
end
project_path = "#{namespace}/#{id}"
- @project = Project.find_with_namespace(project_path)
-
+ @project = Project.find_with_namespace(project_path) ||
+ Project.find_with_namespace(project_path, case_sensitive: false)
if @project and can?(current_user, :read_project, @project)
if @project.path_with_namespace != project_path
diff --git a/app/models/project.rb b/app/models/project.rb
index 88cd88dcb5a..b2a8dde9ba2 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -235,7 +235,7 @@ class Project < ActiveRecord::Base
where('projects.archived = ?', false).where('LOWER(projects.name) LIKE :query', query: "%#{query.downcase}%")
end
- def find_with_namespace(id)
+ def find_with_namespace(id, case_sensitive: true)
namespace_path, project_path = id.split('/')
return nil if !namespace_path || !project_path
@@ -243,11 +243,18 @@ class Project < ActiveRecord::Base
# Use of unscoped ensures we're not secretly adding any ORDER BYs, which
# have a negative impact on performance (and aren't needed for this
# query).
- unscoped.
+ projects = unscoped.
joins(:namespace).
- iwhere('namespaces.path' => namespace_path).
- iwhere('projects.path' => project_path).
- take
+ iwhere('namespaces.path' => namespace_path)
+
+ projects =
+ if case_sensitive
+ projects.where('projects.path' => project_path)
+ else
+ projects.iwhere('projects.path' => project_path)
+ end
+
+ projects.take
end
def visibility_levels
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 4460bf12f96..5090f87c73d 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -51,16 +51,34 @@ describe ProjectsController do
end
context "when requested with case sensitive namespace and project path" do
- it "redirects to the normalized path for case mismatch" do
- get :show, namespace_id: public_project.namespace.path, id: public_project.path.upcase
+ context "when there is a match with the same casing" do
+ it "loads the project" do
+ get :show, namespace_id: public_project.namespace.path, id: public_project.path
- expect(response).to redirect_to("/#{public_project.path_with_namespace}")
+ expect(assigns(:project)).to eq(public_project)
+ expect(response.status).to eq(200)
+ end
end
- it "loads the page if normalized path matches request path" do
- get :show, namespace_id: public_project.namespace.path, id: public_project.path
+ context "when there is a match with different casing" do
+ it "redirects to the normalized path" do
+ get :show, namespace_id: public_project.namespace.path, id: public_project.path.upcase
+
+ expect(assigns(:project)).to eq(public_project)
+ expect(response).to redirect_to("/#{public_project.path_with_namespace}")
+ end
- expect(response.status).to eq(200)
+ context "when there is also a match with the same casing" do
+
+ let!(:other_project) { create(:project, :public, namespace: public_project.namespace, path: public_project.path.upcase) }
+
+ it "loads the exactly matched project" do
+ get :show, namespace_id: public_project.namespace.path, id: public_project.path.upcase
+
+ expect(assigns(:project)).to eq(other_project)
+ expect(response.status).to eq(200)
+ end
+ end
end
end
end